changeset 2958:98aa41c076f5

PSARC/2005/334 Packet Filtering Hooks PSARC/2006/321 ARP packet filtering Hooks 6401219 use of pullupmsg() considered destructive - clears h/w checksum flags 6418698 PSARC/2005/334 - Packet Filtering Hooks API 6449290 package prototype files in usr/src/pkgdefs/SUNWipfr missing CDDL 6449292 package prototype files in usr/src/pkgdefs/SUNWipfu missing CDDL 6449296 Makefiles for ipf kernel module building missing CDDL 6473996 "fastroute" + "nat" packets cause memory leaks in ipfilter
author dr146992
date Fri, 20 Oct 2006 16:37:58 -0700
parents a3f9fceeda60
children 54668e3addac
files deleted_files/usr/src/cmd/ipf/etc/pfil.ap.sh deleted_files/usr/src/cmd/ipf/pfild/Makefile deleted_files/usr/src/cmd/ipf/pfild/pfild.c deleted_files/usr/src/cmd/ipf/pfild/vas.c deleted_files/usr/src/cmd/ipf/svc/pfil deleted_files/usr/src/cmd/ipf/svc/pfil.xml deleted_files/usr/src/uts/common/inet/pfil/compat.h deleted_files/usr/src/uts/common/inet/pfil/ndd.c deleted_files/usr/src/uts/common/inet/pfil/os.h deleted_files/usr/src/uts/common/inet/pfil/pfil.c deleted_files/usr/src/uts/common/inet/pfil/pfil.conf deleted_files/usr/src/uts/common/inet/pfil/pfil.h deleted_files/usr/src/uts/common/inet/pfil/pfild.h deleted_files/usr/src/uts/common/inet/pfil/pfildrv.c deleted_files/usr/src/uts/common/inet/pfil/pfilstream.c deleted_files/usr/src/uts/common/inet/pfil/pkt.c deleted_files/usr/src/uts/common/inet/pfil/qif.c deleted_files/usr/src/uts/common/inet/pfil/qif.h deleted_files/usr/src/uts/intel/pfil/Makefile deleted_files/usr/src/uts/sparc/pfil/Makefile usr/src/cmd/devfsadm/misc_link.c usr/src/cmd/ipf/Makefile usr/src/cmd/ipf/etc/Makefile usr/src/cmd/ipf/etc/pfil.ap.sh usr/src/cmd/ipf/lib/common/getifname.c usr/src/cmd/ipf/lib/common/getsumd.c usr/src/cmd/ipf/pfild/Makefile usr/src/cmd/ipf/pfild/pfild.c usr/src/cmd/ipf/pfild/vas.c usr/src/cmd/ipf/svc/Makefile usr/src/cmd/ipf/svc/ipfilter usr/src/cmd/ipf/svc/ipfilter.xml usr/src/cmd/ipf/svc/pfil usr/src/cmd/ipf/svc/pfil.xml usr/src/cmd/ipf/tools/ip_fil.c usr/src/cmd/ipf/tools/ipf_y.y usr/src/cmd/mdb/Makefile.common usr/src/cmd/mdb/common/modules/arp/arp.c usr/src/cmd/mdb/common/modules/hook/hook.c usr/src/cmd/mdb/common/modules/neti/neti.c usr/src/cmd/mdb/intel/amd64/hook/Makefile usr/src/cmd/mdb/intel/amd64/neti/Makefile usr/src/cmd/mdb/intel/ia32/hook/Makefile usr/src/cmd/mdb/intel/ia32/neti/Makefile usr/src/cmd/mdb/sparc/v9/hook/Makefile usr/src/cmd/mdb/sparc/v9/neti/Makefile usr/src/cmd/svc/prophist/prophist.SUNWcsr usr/src/cmd/svc/seed/Makefile usr/src/cmd/svc/seed/inc.flg usr/src/lib/libsecdb/exec_attr.txt usr/src/pkgdefs/SUNWckr/prototype_i386 usr/src/pkgdefs/SUNWckr/prototype_sparc usr/src/pkgdefs/SUNWhea/prototype_com usr/src/pkgdefs/SUNWipfr/prototype_com usr/src/pkgdefs/SUNWipfr/prototype_i386 usr/src/pkgdefs/SUNWipfr/prototype_sparc usr/src/pkgdefs/SUNWipfu/prototype_com usr/src/pkgdefs/SUNWipfu/prototype_i386 usr/src/pkgdefs/SUNWipfu/prototype_sparc usr/src/pkgdefs/SUNWmdb/prototype_i386 usr/src/pkgdefs/SUNWmdb/prototype_sparc usr/src/pkgdefs/SUNWmdbr/prototype_i386 usr/src/pkgdefs/SUNWmdbr/prototype_sparc usr/src/tools/scripts/bfu.sh usr/src/uts/common/Makefile.files usr/src/uts/common/Makefile.rules usr/src/uts/common/conf/param.c usr/src/uts/common/inet/Makefile usr/src/uts/common/inet/arp/arp.c usr/src/uts/common/inet/arp/arp_netinfo.c usr/src/uts/common/inet/arp/arpddi.c usr/src/uts/common/inet/arp_impl.h usr/src/uts/common/inet/ip.h usr/src/uts/common/inet/ip/ip.c usr/src/uts/common/inet/ip/ip6.c usr/src/uts/common/inet/ip/ip_ftable.c usr/src/uts/common/inet/ip/ip_if.c usr/src/uts/common/inet/ip/ip_multi.c usr/src/uts/common/inet/ip/ip_ndp.c usr/src/uts/common/inet/ip/ip_netinfo.c usr/src/uts/common/inet/ip6.h usr/src/uts/common/inet/ip_if.h usr/src/uts/common/inet/ip_impl.h usr/src/uts/common/inet/ip_ire.h usr/src/uts/common/inet/ip_netinfo.h usr/src/uts/common/inet/ipf/fil.c usr/src/uts/common/inet/ipf/ip_auth.c usr/src/uts/common/inet/ipf/ip_fil_solaris.c usr/src/uts/common/inet/ipf/ip_log.c usr/src/uts/common/inet/ipf/ip_nat.c usr/src/uts/common/inet/ipf/ip_proxy.c usr/src/uts/common/inet/ipf/ip_state.c usr/src/uts/common/inet/ipf/misc.c usr/src/uts/common/inet/ipf/netinet/ip_compat.h usr/src/uts/common/inet/ipf/netinet/ip_fil.h usr/src/uts/common/inet/ipf/netinet/ip_irc_pxy.c usr/src/uts/common/inet/ipf/netinet/ip_nat.h usr/src/uts/common/inet/ipf/netinet/ip_state.h usr/src/uts/common/inet/ipf/solaris.c usr/src/uts/common/inet/pfil/compat.h usr/src/uts/common/inet/pfil/misc.c usr/src/uts/common/inet/pfil/ndd.c usr/src/uts/common/inet/pfil/os.h usr/src/uts/common/inet/pfil/pfil.c usr/src/uts/common/inet/pfil/pfil.conf usr/src/uts/common/inet/pfil/pfil.h usr/src/uts/common/inet/pfil/pfild.h usr/src/uts/common/inet/pfil/pfildrv.c usr/src/uts/common/inet/pfil/pfilstream.c usr/src/uts/common/inet/pfil/pkt.c usr/src/uts/common/inet/pfil/qif.c usr/src/uts/common/inet/pfil/qif.h usr/src/uts/common/inet/tcp.h usr/src/uts/common/inet/tcp/tcp.c usr/src/uts/common/inet/tcp/tcp_fusion.c usr/src/uts/common/inet/udp/udp.c usr/src/uts/common/io/bge/bge_send.c usr/src/uts/common/io/hook.c usr/src/uts/common/io/neti.c usr/src/uts/common/io/stream.c usr/src/uts/common/sys/Makefile usr/src/uts/common/sys/condvar_impl.h usr/src/uts/common/sys/hook.h usr/src/uts/common/sys/hook_event.h usr/src/uts/common/sys/hook_impl.h usr/src/uts/common/sys/neti.h usr/src/uts/common/sys/queue.h usr/src/uts/common/sys/stream.h usr/src/uts/intel/Makefile.intel.shared usr/src/uts/intel/arp/Makefile usr/src/uts/intel/hook/Makefile usr/src/uts/intel/ip/Makefile usr/src/uts/intel/ipf/Makefile usr/src/uts/intel/neti/Makefile usr/src/uts/intel/os/device_policy usr/src/uts/intel/os/minor_perm usr/src/uts/intel/os/name_to_major usr/src/uts/intel/pfil/Makefile usr/src/uts/sparc/Makefile.sparc.shared usr/src/uts/sparc/arp/Makefile usr/src/uts/sparc/hook/Makefile usr/src/uts/sparc/ip/Makefile usr/src/uts/sparc/ipf/Makefile usr/src/uts/sparc/neti/Makefile usr/src/uts/sparc/os/device_policy usr/src/uts/sparc/os/minor_perm usr/src/uts/sparc/os/name_to_major usr/src/uts/sparc/pfil/Makefile
diffstat 148 files changed, 15480 insertions(+), 8177 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/cmd/ipf/etc/pfil.ap.sh	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,69 @@
+#!/sbin/sh
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+
+#ident	"%Z%%M%	%I%	%E% SMI"
+
+case "$MACH" in
+  "i386" )
+	echo "# IP Filter pfil autopush setup
+#
+# See the autopush(1M) manpage for more information.
+#
+# Format of the entries in this file is:
+#
+#major  minor lastminor modules
+
+#iprb	-1	0	pfil
+#elxl	-1	0	pfil
+#e1000g	-1	0	pfil
+#bge	-1	0	pfil
+#nf	-1	0	pfil
+#fa	-1	0	pfil
+#ci	-1	0	pfil
+#el	-1	0	pfil
+#ipdptp	-1	0	pfil
+#lane	-1	0	pfil
+#dnet	-1	0	pfil
+#pcelx	-1	0	pfil
+#spwr	-1	0	pfil
+#ce	-1	0	pfil
+
+" > pfil.ap
+	;;
+  "sparc" )
+	echo "# IP Filter pfil autopush setup
+#
+# See autopush(1M) manpage for more information.
+#
+# Format of the entries in this file is:
+#
+#major  minor lastminor modules
+
+#le	-1	0	pfil
+#qe	-1	0	pfil
+#hme	-1	0	pfil
+#qfe	-1	0	pfil
+#eri	-1	0	pfil
+#ce	-1	0	pfil
+#e1000g	-1	0	pfil
+#bge	-1	0	pfil
+#be	-1	0	pfil
+#vge	-1	0	pfil
+#ge	-1	0	pfil
+#nf	-1	0	pfil
+#fa	-1	0	pfil
+#ci	-1	0	pfil
+#el	-1	0	pfil
+#ipdptp	-1	0	pfil
+#lane	-1	0	pfil
+#dmfe	-1	0	pfil
+" >pfil.ap
+	;;
+  * )
+	echo "Unknown architecture."
+	exit 1
+	;;
+esac
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/cmd/ipf/pfild/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,37 @@
+#
+# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+PROG=	pfild
+
+OBJS=	pfild.o vas.o
+SRCS=	$(OBJS:.o=.c)
+
+include ../../Makefile.cmd
+include ../Makefile.ipf
+
+LDLIBS          += $(LIBBPF) -lsocket -lnsl
+CFLAGS		+= -DNDEBUG -D_XOPEN_SOURCE=500 -D__EXTENSIONS__
+CPPFLAGS        += -I. -DIPFILTER_LOOKUP -DIPFILTER_LOG
+CLEANFILES	+= $(OBJS)
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+	$(LINK.c) $(OBJS) -o $@ $(LDLIBS)
+	$(POST_PROCESS)
+
+install: all $(ROOTUSRSBINPROG)
+
+clean:
+	-$(RM) $(OBJS) $(PROG)
+
+lint:	lint_SRCS
+
+include ../../Makefile.targ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/cmd/ipf/pfild/pfild.c	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,616 @@
+/*
+ * Copyright (C) 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <net/if.h>
+#include <net/route.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <stropts.h>
+#include <stdlib.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#include "pfild.h"
+
+extern int vas(const struct pfil_ifaddrs *, int);
+
+/*
+ * pfild.c:  interface data and packet transmission daemon for pfil
+ *
+ * pfild provides the pfil kernel module with certain data that are not
+ * directly available to kernel code using supported OS interfaces.  pfild
+ * accesses the routing tables and network interface parameters using
+ * interfaces readily available to a user space daemon, copies the data into
+ * the kernel via /dev/pfil, and waits for any changes to the data.
+ *
+ * pfild also provides a way for the kernel module to originate IP packets
+ * without resorting to unsupported kernel interfaces.  If the kernel
+ * sends up an M_DATA message, pfild sends it on a raw IP socket so that it
+ * gets routed and transmitted as a normal packet.
+ */
+
+
+/* file descriptors for talking to pfil, ifnet, routing kernel modules */
+static int pfil_fd, ip_fd, icmp6_ip6_fd, tcp_ip6_fd, route_fd;
+
+/*
+ * flag indicates that some interface or routing data have changed since
+ * last update.
+ */
+static int flag = 1;
+/*
+ * debuglevel indicates to what level debugging messages should be emitted.
+ */
+static int debuglevel = 0;
+
+/* Wait for this many ms of quiet time after changes before doing an update. */
+#define	QUIETTIME 200
+
+
+/*
+ * Send a message to the pfil kernel module.
+ * Returns zero for success, otherwise non-zero with errror in errno.
+ */
+int
+pfil_msg(uint32_t cmd, void *buf, size_t len)
+{
+	int error;
+
+	if (debuglevel > 0)
+		(void) fprintf(stderr, "pfil_msg(%x,%p,%d)\n", cmd, buf, len);
+
+	if (pfil_fd >= 0) {
+		struct strbuf ctl, data;
+
+		ctl.buf = (void *)&cmd;
+		ctl.len = sizeof (cmd);
+		data.buf = buf;
+		data.len = len;
+
+		error = putmsg(pfil_fd, &ctl, &data, 0);
+		if (debuglevel > 0)
+			(void) fprintf(stderr,
+			    "pfild:pfil_msg():putmsg(%d,%p,%p,0) = %d\n",
+			    pfil_fd, &ctl, &data, 0, error);
+	} else {
+		error = 0;
+		if (debuglevel > 0)
+			(void) fprintf(stderr,
+			    "pfild:pfil_msg():pfil_fd < 0\n");
+	}
+
+	return (error);
+}
+
+
+/*
+ * Handle a PF_ROUTE message.  If an address has been added or deleted, treat
+ * this as an indication that some interface data has been udpated.  If a route
+ * has been added or deleted, treat this as an indication that the routing
+ * table has been updated.  The current implementation completely updates both
+ * sets of data when either kind of change is indicated.
+ *
+ * p points to, and size indicates the size of, the message.
+ */
+static void
+handle_msg(const ifa_msghdr_t *p, size_t size)
+{
+	if (size < sizeof (*p) ||
+	    size < p->ifam_msglen ||
+	    p->ifam_version != RTM_VERSION) {
+		if (debuglevel > 0)
+			(void) fprintf(stderr,
+			    "Not a valid version %u RTM message - "
+			    "%u bytes version %u\n",
+			    RTM_VERSION, size, p->ifam_version);
+		return;
+	}
+
+	switch (p->ifam_type) {
+	case RTM_NEWADDR:
+	case RTM_DELADDR:
+	case RTM_ADD:
+	case RTM_DELETE:
+		flag = 1;
+		break;
+	default:
+		break;
+	}
+
+	if (debuglevel > 0)
+		(void) fprintf(stderr,
+		    "pfild:handle_msg(): msg rcvd %d flag %d\n",
+		    p->ifam_type, flag);
+}
+
+
+#include <arpa/inet.h>
+static const char *
+dumpaddr(void *p)
+{
+	static char buf[INET6_ADDRSTRLEN];
+	struct sockaddr_in *sin = p;
+	struct sockaddr_in6 *sin6 = p;
+	switch (sin->sin_family) {
+	case AF_INET:
+		return (inet_ntop(sin->sin_family, &sin->sin_addr, buf,
+		    sizeof (buf)));
+	case AF_INET6:
+		return (inet_ntop(sin6->sin6_family, &sin6->sin6_addr, buf,
+		    sizeof (buf)));
+	default:
+		return ("<none>");
+	}
+}
+
+
+#define	ERRBUFSIZE 100
+static char errbuf[ERRBUFSIZE];
+
+#define	LIFN_MARGIN 5		/* a few extra in case things are changing */
+
+/*
+ * Fetch the address configuration data for all interfaces and push it into
+ * the pfil kernel module.  Fetch the routing table, compute the valid address
+ * set data for all interfaces and push it into the pfil kernel module.
+ */
+static int
+do_update(void)
+{
+	int numifs, i;
+	struct lifreq *lifrbuf;
+	struct lifconf lifc;
+	struct pfil_ifaddrs *ifaddrlist;
+	struct lifnum lifn;
+	const int lifc_flags = 0;
+	void *buf;
+	size_t bufsize;
+
+	flag = 0;
+
+	lifn.lifn_family = AF_UNSPEC;
+	lifn.lifn_flags = lifc_flags;
+	if (ioctl(ip_fd, SIOCGLIFNUM, (char *)&lifn) < 0) {
+		(void) snprintf(errbuf, ERRBUFSIZE, "SIOCGLIFNUM: %s",
+		    strerror(errno));
+		return (-1);
+	}
+
+	bufsize = (lifn.lifn_count + LIFN_MARGIN) * sizeof (struct lifreq);
+	buf = malloc(bufsize);
+	if (buf == NULL) {
+		(void) snprintf(errbuf, ERRBUFSIZE, "malloc: %s",
+		    strerror(errno));
+		return (-1);
+	}
+	lifrbuf = buf;
+	lifc.lifc_family = AF_UNSPEC;
+	lifc.lifc_flags = lifc_flags;
+	lifc.lifc_buf = buf;
+	lifc.lifc_len = bufsize;
+	if (ioctl(ip_fd, SIOCGLIFCONF, (char *)&lifc) < 0) {
+		(void) snprintf(errbuf, ERRBUFSIZE, "SIOCGLIFCONF: %s",
+		    strerror(errno));
+		free(buf);
+		return (-1);
+	}
+
+	numifs = lifc.lifc_len / sizeof (struct lifreq);
+
+	/* Allocate memory for the number of interfaces retrieved. */
+	ifaddrlist = calloc(numifs, sizeof (struct pfil_ifaddrs));
+	if (ifaddrlist == NULL) {
+		(void) snprintf(errbuf, ERRBUFSIZE, "calloc: %s",
+		    strerror(errno));
+		free(buf);
+		return (-1);
+	}
+
+	/* Populate the interface entries in the ifaddrlist. */
+	for (i = 0; i < numifs; i++) {
+		int isv6 = (lifrbuf[i].lifr_addr.ss_family == AF_INET6);
+		int fd = (isv6 ? icmp6_ip6_fd : ip_fd);
+
+		(void) strncpy(ifaddrlist[i].name, lifrbuf[i].lifr_name,
+		    LIFNAMSIZ);
+		(void) memcpy(&ifaddrlist[i].localaddr, &lifrbuf[i].lifr_addr,
+		    sizeof (ifaddrlist[i].localaddr));
+
+		if (ioctl(fd, SIOCGLIFNETMASK, &lifrbuf[i]) < 0) {
+			(void) snprintf(errbuf, ERRBUFSIZE,
+			    "SIOCGLIFNETMASK %.*s: %s",
+			    LIFNAMSIZ, ifaddrlist[i].name, strerror(errno));
+			free(ifaddrlist);
+			free(buf);
+			return (-1);
+		}
+		(void) memcpy(&ifaddrlist[i].netmask, &lifrbuf[i].lifr_addr,
+		    sizeof (ifaddrlist[i].netmask));
+
+		if (ioctl(fd, SIOCGLIFBRDADDR, &lifrbuf[i]) < 0) {
+			if (errno != EADDRNOTAVAIL) {
+				(void) snprintf(errbuf, ERRBUFSIZE,
+				    "SIOCGLIFBRDADDR %.*s: %s",
+				    LIFNAMSIZ, ifaddrlist[i].name,
+				    strerror(errno));
+				free(ifaddrlist);
+				free(buf);
+				return (-1);
+			}
+		} else {
+			(void) memcpy(&ifaddrlist[i].broadaddr,
+			    &lifrbuf[i].lifr_broadaddr,
+			    sizeof (ifaddrlist[i].broadaddr));
+		}
+
+		if (ioctl(fd, SIOCGLIFDSTADDR, &lifrbuf[i]) < 0) {
+			if (errno != EADDRNOTAVAIL) {
+				(void) snprintf(errbuf, ERRBUFSIZE,
+				    "SIOCGLIFDSTADDR %.*s: %s",
+				    LIFNAMSIZ, ifaddrlist[i].name,
+				    strerror(errno));
+				free(ifaddrlist);
+				free(buf);
+				return (-1);
+			}
+		} else {
+			(void) memcpy(&ifaddrlist[i].dstaddr,
+			    &lifrbuf[i].lifr_dstaddr,
+			    sizeof (ifaddrlist[i].dstaddr));
+		}
+
+		if (ioctl(fd, SIOCGLIFMTU, &lifrbuf[i]) < 0) {
+			(void) snprintf(errbuf, ERRBUFSIZE,
+			    "SIOCGLIFDSTADDR %.*s: %s",
+			    LIFNAMSIZ, ifaddrlist[i].name,
+			    strerror(errno));
+			free(ifaddrlist);
+			free(buf);
+			return (-1);
+		} else {
+			ifaddrlist[i].mtu = lifrbuf[i].lifr_mtu;
+		}
+
+		if (debuglevel > 0) {
+			(void) fprintf(stderr, "%.*s:\n",
+			    LIFNAMSIZ, ifaddrlist[i].name);
+			(void) fprintf(stderr, "	localaddr %s (%d)\n",
+			    dumpaddr(&ifaddrlist[i].localaddr),
+			    ifaddrlist[i].localaddr.in.sin_family);
+			(void) fprintf(stderr, "	netmask %s (%d)\n",
+			    dumpaddr(&ifaddrlist[i].netmask),
+			    ifaddrlist[i].netmask.in.sin_family);
+			(void) fprintf(stderr, "	broadaddr %s (%d)\n",
+			    dumpaddr(&ifaddrlist[i].broadaddr),
+			    ifaddrlist[i].broadaddr.in.sin_family);
+			(void) fprintf(stderr, "	dstaddr %s (%d)\n",
+			    dumpaddr(&ifaddrlist[i].dstaddr),
+			    ifaddrlist[i].dstaddr.in.sin_family);
+			(void) fprintf(stderr, "	mtu %u\n",
+			    ifaddrlist[i].mtu);
+		}
+	}
+
+	free(buf);
+
+	/*
+	 * Now send this table of interfaces and addresses down into
+	 * the pfil kernel module.
+	 */
+	if (pfil_msg(PFILCMD_IFADDRS,
+	    ifaddrlist, i * sizeof (struct pfil_ifaddrs)) < 0) {
+		(void) snprintf(errbuf, ERRBUFSIZE,
+		    "PFILCMD_IFADDRS: %s", strerror(errno));
+		free(ifaddrlist);
+		return (-1);
+	}
+
+	/*
+	 * Next, compute and send the table of valid addresses.
+	 */
+
+	if (vas(ifaddrlist, numifs) < 0) {
+		(void) snprintf(errbuf, ERRBUFSIZE,
+		    "PFILCMD_IFADDRSET: %s", strerror(errno));
+		free(ifaddrlist);
+		return (-1);
+	}
+
+	free(ifaddrlist);
+
+	return (0);
+}
+
+
+/*
+ * Send an IPv6 packet out from the system using sendmsg on the raw IP socket
+ * through the ancillary data.
+ */
+static int
+send_ip6_pkt(const void *pkt, size_t len)
+{
+	const struct ip6_hdr *iph = pkt;
+
+	struct sockaddr_in6 sin6;
+	struct iovec iovec;
+	struct msghdr msghdr;
+	struct cmsghdr *cmsgp;
+	struct in6_pktinfo *pktinfop;
+	unsigned char ancdatabuf[sizeof (*cmsgp) + sizeof (*pktinfop) + 100];
+	size_t ancdatalen;
+	int fd;
+
+	cmsgp = (struct cmsghdr *)ancdatabuf;
+	pktinfop = (struct in6_pktinfo *)CMSG_DATA(cmsgp);
+	cmsgp->cmsg_len = ((char *)(pktinfop + 1) - (char *)cmsgp);
+	cmsgp->cmsg_level = IPPROTO_IPV6;
+	cmsgp->cmsg_type = IPV6_PKTINFO;
+	memcpy(&pktinfop->ipi6_addr, &iph->ip6_src,
+		sizeof (pktinfop->ipi6_addr));
+	pktinfop->ipi6_ifindex = 0;
+	ancdatalen = ((char *)(pktinfop + 1) - (char *)cmsgp);
+
+	sin6.sin6_family = AF_INET6;
+	memcpy(&sin6.sin6_addr, &iph->ip6_dst, sizeof (sin6.sin6_addr));
+	sin6.sin6_port = 0;
+	sin6.sin6_scope_id = 0;
+	sin6.sin6_flowinfo = iph->ip6_flow & IPV6_FLOWINFO_TCLASS;
+
+	iovec.iov_base = (char *)(iph + 1);
+	iovec.iov_len = len - sizeof (*iph);
+	msghdr.msg_name = &sin6;
+	msghdr.msg_namelen = sizeof (sin6);
+	msghdr.msg_iov = &iovec;
+	msghdr.msg_iovlen = 1;
+	msghdr.msg_control = ancdatabuf;
+	msghdr.msg_controllen = ancdatalen;
+	msghdr.msg_flags = 0;
+
+	if (iph->ip6_nxt == IPPROTO_ICMPV6)
+		fd = icmp6_ip6_fd;
+	else if (iph->ip6_nxt == IPPROTO_TCP)
+		fd = tcp_ip6_fd;
+	else {
+		errno = EPROTONOSUPPORT;
+		return (-1);
+	}
+	return (sendmsg(fd, &msghdr, 0));
+}
+
+
+/*
+ * Send an arbitrary IP packet out from the system using sendto/sendmsg on the
+ * raw IP socket.  Due to the awkwardness of the IPv6 socket API, IPv6 packets
+ * are limited to ICMP and TCP; other protocols are dropped.
+ */
+static void
+sendpkt(const void *buf, int len)
+{
+	const struct ip *iph = buf;
+	int n;
+
+	if (debuglevel > 0) {
+		fprintf(stderr, "pfild sendpkt %u bytes:\n", len);
+		fprintf(stderr, " %08X %08X %08X %08X\n",
+			((uint32_t *)buf)[0],
+			((uint32_t *)buf)[1],
+			((uint32_t *)buf)[2],
+			((uint32_t *)buf)[3]);
+		fprintf(stderr, " %08X %08X %08X %08X\n",
+			((uint32_t *)buf)[4],
+			((uint32_t *)buf)[5],
+			((uint32_t *)buf)[6],
+			((uint32_t *)buf)[7]);
+		fprintf(stderr, " %08X %08X %08X %08X\n",
+			((uint32_t *)buf)[8],
+			((uint32_t *)buf)[9],
+			((uint32_t *)buf)[10],
+			((uint32_t *)buf)[11]);
+	}
+
+	if (iph->ip_v == 4 && len >= 20) {
+		struct sockaddr_in sin;
+		sin.sin_family = AF_INET;
+		sin.sin_port = 0;
+		sin.sin_addr = iph->ip_dst;
+		n = sendto(ip_fd, buf, len, 0, (void *)&sin, sizeof (sin));
+	} else if (iph->ip_v == 6 && len > 40) {
+		n = send_ip6_pkt(buf, len);
+	} else {
+		n = -1;
+		errno = EINVAL;
+	}
+
+	if (n < 0)
+		perror("pfild: raw socket send");
+}
+
+
+static void usage(const char *prog)
+{
+	fprintf(stderr, "%s: [-d]\n", prog);
+	exit(1);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+	int c, n;
+	const int on = 1;
+	int make_daemon = 1;
+	struct pollfd pollfds[2];
+	union { char bytes[1024]; ifa_msghdr_t msg; } buffer;
+	int pid;
+	struct icmp6_filter  filter;
+
+	while ((c = getopt(argc, argv, "d")) != -1) {
+		switch (c) {
+		case '?' :
+			usage(argv[0]);
+			break;
+		case 'd' :
+			make_daemon = 0;
+			debuglevel++;
+			break;
+		}
+	}
+
+	pfil_fd = open("/dev/pfil", O_RDWR);
+	if (pfil_fd < 0) {
+		perror("pfild: open(/dev/pfil)");
+		return (1);
+	}
+
+	ip_fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+	if (ip_fd < 0) {
+		perror("pfild: inet socket");
+		return (1);
+	}
+	if (setsockopt(ip_fd, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)) < 0) {
+		perror("pfild: inet socket IP_HDRINCL option");
+		return (1);
+	}
+
+	icmp6_ip6_fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+	if (icmp6_ip6_fd < 0) {
+		perror("pfild: inet6 ICMP6 socket");
+		return (1);
+	}
+	/*
+	 *  ICMPv6 raw socket by default passes all ICMPv6 message received
+	 *  to the application.  We don't care about them, so simply block them
+	 *  all.
+	 */
+	ICMP6_FILTER_SETBLOCKALL(&filter);
+	if (setsockopt(icmp6_ip6_fd, IPPROTO_ICMPV6, ICMP6_FILTER,
+			&filter, sizeof (filter)) < 0) {
+		perror("pfild: inet6 ICMP6 socket type filtering option");
+		return (1);
+	}
+
+	tcp_ip6_fd = socket(AF_INET6, SOCK_RAW, IPPROTO_TCP);
+	if (tcp_ip6_fd < 0) {
+		perror("pfild: inet6 TCP socket");
+		return (1);
+	}
+
+	route_fd = socket(PF_ROUTE, SOCK_RAW, 0);
+	if (route_fd < 0) {
+		perror("pfild: socket(PF_ROUTE)");
+		return (1);
+	}
+
+	if (make_daemon) {
+		/* Background */
+		if ((pid = fork()) > 0)
+			return (0);
+		if (pid < 0) {
+			(void) fprintf(stderr, "%s: fork() failed %s\n",
+			    argv[0], strerror(errno));
+			return (1);
+			/* NOTREACHED */
+		}
+		(void) setsid();
+		(void) close(0);
+		(void) close(1);
+		(void) close(2);
+		(void) open("/dev/null", O_RDWR);
+		(void) dup(0);
+		(void) dup(0);
+		(void) chdir("/");
+	}
+
+	/*
+	 * Main loop:  Poll for messages from PF_ROUTE socket or pfil stream.
+	 * PF_ROUTE messages may indicate a need to update the kernel module's
+	 * interface data.  pfil messages contain packets to be transmitted.
+	 * Errors in processing don't terminate the program, but errors in
+	 * polling will terminate the program to avoid busy looping.
+	 */
+
+	pollfds[0].fd = route_fd;
+	pollfds[0].events = POLLRDNORM;
+	pollfds[1].fd = pfil_fd;
+	pollfds[1].events = POLLRDNORM;
+
+	while (1) {
+		if (flag) {
+			/* Wait for a moment of quiet, then do the update. */
+			n = poll(pollfds, 1, QUIETTIME);
+			if (n < 1 || !(pollfds[0].revents & POLLRDNORM)) {
+				if (do_update() != 0 && make_daemon == 0)
+					(void) fprintf(stderr, "pfild: %s\n",
+					    errbuf);
+			}
+		}
+
+		if (poll(pollfds, 2, -1) < 0) {
+			perror("pfild: poll()");
+			return (1);
+		}
+
+		/* Check for route_fd message. */
+		if (pollfds[0].revents & POLLRDNORM) {
+			n = read(route_fd, &buffer, sizeof (buffer));
+
+			if (n < 1) {
+				if (n < 0)
+					perror("pfild: read(PF_ROUTE)");
+				else
+					(void) fprintf(stderr,
+					    "pfild: read(PF_ROUTE) EOF\n");
+				return (1);
+			}
+
+			handle_msg(&buffer.msg, n);
+		}
+
+		/* Check for pfil_fd message. */
+		if (pollfds[1].revents & POLLRDNORM) {
+			char pktbuf[IP_MAXPACKET];
+			struct strbuf ctl, data;
+			int flags;
+
+			ctl.maxlen = 0;	/* We don't want any control message. */
+			ctl.buf = pktbuf;
+			data.maxlen = sizeof (pktbuf);
+			data.buf = pktbuf;
+			flags = 0;
+
+			n = getmsg(pfil_fd, &ctl, &data, &flags);
+
+			if (n < 0) {
+				perror("pfild: getmsg(pfil)");
+				return (1);
+			}
+			if (n > 0) {
+				fprintf(stderr,
+				    "pfild: invalid packet from kernel "
+				    "n=%d ctl.len=%u data.len=%u\n",
+				    n, ctl.len, data.len);
+				return (1);
+			}
+
+			sendpkt(data.buf, data.len);
+		}
+	}
+
+	/* NOTREACHED */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/cmd/ipf/pfild/vas.c	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,1258 @@
+/*
+ * Copyright (C) 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stream.h>
+#include <stropts.h>
+#include <sys/strstat.h>
+#include <sys/sysmacros.h>
+#include <sys/tihdr.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <net/route.h>
+#include <inet/common.h>
+#include <inet/mib2.h>
+#include <inet/ip.h>
+#include <inet/ip6.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <sys/systeminfo.h>
+#include <arpa/inet.h>
+#include "pfild.h"
+
+#ifndef MIN
+#define	MIN(a, b)	(((a) < (b)) ? (a) : (b))
+#endif
+
+extern int pfil_msg(uint32_t, void *, size_t);
+
+/*
+ * vas.c:  Valid Address Set computation and communication for pfild
+ *
+ * pfild computes a "valid source address set" for each interface and hands the
+ * resulting data to the pfil module which makes it available to pfil clients.
+ * The ipf module uses the valid address sets to implement the fr_chksrc
+ * feature (automatic protection from source address spoofing).
+ *
+ * A valid source address for a packet received on given interface is defined
+ * as an address which, if used as a destination, would be routed to that
+ * interface.  This code assumes that only inbound traffic will be tested
+ * against the valid address sets; thus all local and loopback addresses are
+ * considered invalid.
+ *
+ * The TPI MIB interface is used to read the current routing table.  A
+ * request (T_SVR4_OPTMGMT_REQ) is sent to /dev/arp and the replies are read,
+ * discarding most of them, but saving the two that contain the IPv4 and IPv6
+ * routing tables.  Also inspected are two other messages that each happen to
+ * contain a constant needed to parse the routing table messages.
+ *
+ * An address set is represented as a sorted list of mutually discontiguous
+ * non-empty inclusive spans.  In the kernel, this list can be efficiently
+ * binary-searched.  In user space, we can compute unions and intersections of
+ * address sets.  In either case, IPv4 addresses are stored in host byte order
+ * for efficient numerical comparisons.  IPv6 addresses will be compared
+ * byte-at-a-time so they are kept in conventional struct in6_addr form
+ * (network byte order).
+ */
+
+
+/*
+ * Defining macro used in IPv6 address comparation, add/minus,
+ * increase/decrease.
+ */
+
+typedef	union	i6addr	{
+	uint32_t	i6[4];
+} i6addr_t;
+
+#define	I60(x)	(((i6addr_t *)(x))->i6[0])
+#define	I61(x)	(((i6addr_t *)(x))->i6[1])
+#define	I62(x)	(((i6addr_t *)(x))->i6[2])
+#define	I63(x)	(((i6addr_t *)(x))->i6[3])
+
+#define	HI60(x)	ntohl(((i6addr_t *)(x))->i6[0])
+#define	HI61(x)	ntohl(((i6addr_t *)(x))->i6[1])
+#define	HI62(x)	ntohl(((i6addr_t *)(x))->i6[2])
+#define	HI63(x)	ntohl(((i6addr_t *)(x))->i6[3])
+
+#define	IP6_EQ(a, b)	(IN6_ARE_ADDR_EQUAL(a, b))
+#define	IP6_GT(a, b)	(HI60(a) > HI60(b) || (HI60(a) == HI60(b) && \
+			(HI61(a) > HI61(b) || (HI61(a) == HI61(b) && \
+			(HI62(a) > HI62(b) || (HI62(a) == HI62(b) && \
+			HI63(a) > HI63(b)))))))
+#define	IP6_LT(a, b)	(HI60(a) < HI60(b) || (HI60(a) == HI60(b) && \
+			(HI61(a) < HI61(b) || (HI61(a) == HI61(b) && \
+			(HI62(a) < HI62(b) || (HI62(a) == HI62(b) && \
+			HI63(a) < HI63(b)))))))
+#define	IP6_GE(a, b)	(IP6_EQ(a, b) || IP6_GT(a, b))
+#define	IP6_LE(a, b)	(IP6_EQ(a, b) || IP6_LT(a, b))
+
+#define	NLADD(n, x)	htonl(ntohl(n) + (x))
+#define	NLMIN(n, x)	htonl(ntohl(n) - (x))
+#define	IP6_INC(a)	\
+		{ i6addr_t *_i6 = (i6addr_t *)(a); \
+		_i6->i6[3] = NLADD(_i6->i6[3], 1); \
+		if (_i6->i6[3] == 0) { \
+			_i6->i6[2] = NLADD(_i6->i6[2], 1); \
+			if (_i6->i6[2] == 0) { \
+				_i6->i6[1] = NLADD(_i6->i6[1], 1); \
+				if (_i6->i6[1] == 0) { \
+					_i6->i6[0] = NLADD(_i6->i6[0], 1); \
+				} \
+			} \
+		} \
+		}
+#define	IP6_DEC(a)	\
+		{ i6addr_t *_i6 = (i6addr_t *)(a); \
+		_i6->i6[3] = NLMIN(_i6->i6[3], 1); \
+		if (_i6->i6[3] == 0xFFFFFFFFU) { \
+			_i6->i6[2] = NLMIN(_i6->i6[2], 1); \
+			if (_i6->i6[2] == 0xFFFFFFFFU) { \
+				_i6->i6[1] = NLMIN(_i6->i6[1], 1); \
+				if (_i6->i6[1] == 0xFFFFFFFFU) { \
+					_i6->i6[0] = NLMIN(_i6->i6[0], 1); \
+				} \
+			} \
+		} \
+		}
+
+#define	IP6_FIRST(a, m)	\
+		{ if ((m) > 96) { \
+			I63(a) = ntohl(I63(a)); \
+			I63(a) &= (0xFFFFFFFF << (128 - (m))); \
+			I63(a) = htonl(I63(a)); \
+		} else if ((m) > 64) { \
+			I62(a) = ntohl(I62(a)); \
+			I62(a) &= (0xFFFFFFFF << (96 - (m))); \
+			I62(a) = htonl(I62(a)); \
+			I63(a) = 0; \
+		} else if ((m) > 32) { \
+			I61(a) = ntohl(I61(a)); \
+			I61(a) &= (0xFFFFFFFF << (64 - (m))); \
+			I61(a) = htonl(I61(a)); \
+			I62(a) = 0; \
+			I63(a) = 0; \
+		} else if ((m) > 0) { \
+			I60(a) = ntohl(I60(a)); \
+			I60(a) &= (0xFFFFFFFF << (32 - (m))); \
+			I60(a) = htonl(I60(a)); \
+			I61(a) = 0; \
+			I62(a) = 0; \
+			I63(a) = 0; \
+		} else { \
+			I60(a) = 0; \
+			I61(a) = 0; \
+			I62(a) = 0; \
+			I63(a) = 0; \
+		} \
+		}
+#define	IP6_LAST(a, m) \
+		{ if ((m) == 128) { \
+		} else if ((m) >= 96) { \
+			I63(a) = ntohl(I63(a)); \
+			I63(a) |= (0xFFFFFFFF >> ((m) - 96)); \
+			I63(a) = htonl(I63(a)); \
+		} else if ((m) >= 64) { \
+			I62(a) = ntohl(I62(a)); \
+			I62(a) |= (0xFFFFFFFF >> ((m) - 64)); \
+			I62(a) = htonl(I62(a)); \
+			I63(a) = 0xFFFFFFFFU; \
+		} else if ((m) >= 32) { \
+			I61(a) = ntohl(I61(a)); \
+			I61(a) |= (0xFFFFFFFF >> ((m) - 32)); \
+			I61(a) = htonl(I61(a)); \
+			I62(a) = 0xFFFFFFFFU; \
+			I63(a) = 0xFFFFFFFFU; \
+		} else if ((m) >= 0) { \
+			I60(a) = ntohl(I60(a)); \
+			I60(a) |= (0xFFFFFFFF >>  (m)); \
+			I60(a) = htonl(I60(a)); \
+			I61(a) = 0xFFFFFFFFU; \
+			I62(a) = 0xFFFFFFFFU; \
+			I63(a) = 0xFFFFFFFFU; \
+		} \
+		}
+
+
+/*
+ * User space uses a linked list of spans, rather than the array that is
+ * used in the kernel and in the /dev/pfil messages.
+ */
+
+struct spannode {
+	struct spannode *next;
+	union {
+		struct pfil_v4span v4;
+		struct pfil_v6span v6;
+	} span;
+};
+
+struct addrset {
+	const char *name;
+	uint8_t af;
+	struct spannode *head;
+};
+
+/*
+ * Allocate and initialize a new struct addrset.
+ * Returns pointer to new instance or NULL for allocation failure.
+ */
+static struct addrset *
+new_addrset(const char *name, uint8_t af)
+{
+	struct addrset *asp = malloc(sizeof (*asp));
+
+	if (asp == NULL)
+		return (NULL);
+
+	asp->name = name;
+	asp->af = af;
+	asp->head = NULL;
+
+	return (asp);
+}
+
+/*
+ * Free an addrset instance.
+ */
+static void
+delete_addrset(struct addrset *asp)
+{
+	struct spannode *tmp;
+	while (asp->head != NULL) {
+		tmp = asp->head->next;
+		free(asp->head);
+		asp->head = tmp;
+	}
+	free(asp);
+}
+
+/*
+ * Add a single IPv4 address or a prefix to a set.
+ * Returns 0 for success, non-zero for failure (allocation error).
+ * addr and mask are passed in network byte order, but immediately converted
+ * to host byte order for comparisons.
+ */
+static int
+addrset_add_v4(struct addrset *asp, ipaddr_t addr, ipaddr_t mask)
+{
+	struct spannode **ptpn, *p;
+	uint32_t first, last;		/* host byte order */
+
+	assert(asp->af == AF_INET);
+
+	first = ntohl(addr & mask);
+	last = ntohl(addr | ~mask);
+
+	/*
+	 * Search through the list linearly, looking for either:  an entry
+	 * contiguous to the one being added (with which we will merge) or a
+	 * discontiguous entry with a higher address (before which we will
+	 * insert).  If no match, we will append at the end.
+	 */
+	for (ptpn = &asp->head; (p = *ptpn) != NULL; ptpn = &p->next) {
+		if (first > 0 && first-1 > p->span.v4.last)
+			continue;
+		if (last == 0xFFFFFFFF || last+1 >= p->span.v4.first) {
+			/* Merge with this entry. */
+			if (first < p->span.v4.first)
+				p->span.v4.first = first;
+			while (last > p->span.v4.last) {
+				struct spannode *next = p->next;
+
+				if (next != NULL &&
+				    last >= next->span.v4.first - 1) {
+					/* Merge this span with the next. */
+					p->span.v4.last = next->span.v4.last;
+					p->next = next->next;
+					free(next);
+				} else {
+					p->span.v4.last = last;
+				}
+			}
+			return (0);
+		} else {
+			/* Found the insertion point; exit the loop. */
+			break;
+		}
+	}
+
+	/* ptpn now points to the "previous next" where we need to insert. */
+
+	p = malloc(sizeof (*p));
+	if (p == NULL)
+		return (1);
+	p->span.v4.first = first;
+	p->span.v4.last = last;
+	p->next = *ptpn;
+	*ptpn = p;
+
+	return (0);
+}
+
+/*
+ * Remove one range of IPv4 addresses from a set.
+ */
+static int
+addrset_delete_v4(struct addrset *asp, uint32_t first, uint32_t last)
+{
+	struct spannode **ptpn, *p;
+
+	/*
+	 * Search through the list linearly, looking for any of:  an entry
+	 * entirely contained with the range being deleted (which we will
+	 * delete from the list) or an entry overlapping the first address of
+	 * the range (which we will truncate at its end) or an entry
+	 * overlapping the last address of the range (which we will truncate at
+	 * its beginning) or an entry which entirely contains the range being
+	 * deleted plus at least one address beyond in each direction (which we
+	 * will split into two entries) or an entry with a higher address than
+	 * we are deleting (at which point we are done).
+	 */
+	for (ptpn = &asp->head; (p = *ptpn) != NULL; ptpn = &p->next) {
+		if (p->span.v4.first > last)
+			return (0);		/* all done */
+		if (p->span.v4.last < first)
+			continue;	/* keep searching */
+		while (p->span.v4.first >= first &&
+		    p->span.v4.last <= last) {
+			/* Delete a span entirely. */
+			*ptpn = p->next;
+			free(p);
+			p = *ptpn;
+			if (p == NULL || p->span.v4.first > last)
+				return (0);	/* all done */
+		}
+		if (p->span.v4.first >= first) {
+			/* Truncate a span at its beginning. */
+			p->span.v4.first = last + 1;
+		} else if (p->span.v4.last <= last) {
+			/* Truncate a span at its end. */
+			p->span.v4.last = first - 1;
+		} else {
+			/* Split a span into two. */
+			struct spannode *p2 = malloc(sizeof (*p2));
+			if (p2 == NULL)
+				return (1);
+			p2->span.v4.first = last + 1;
+			p2->span.v4.last = p->span.v4.last;
+			p2->next = p->next;
+			p->span.v4.last = first - 1;
+			p->next = p2;
+		}
+	}
+
+	return (0);
+}
+
+/*
+ * Add a single IPv6 address or a prefix to a set.
+ * Returns 0 for success, non-zero for failure (allocation error).
+ * addr is passed in network byte order, but keep this order.
+ * prefixlen is the prefix length.
+ */
+static int
+addrset_add_v6(struct addrset *asp, in6_addr_t addr, int prefixlen)
+{
+	struct spannode **ptpn, *p;
+	in6_addr_t first, last, temp;
+	const in6_addr_t ipv6_all_zeros = IN6ADDR_ANY_INIT;
+	const in6_addr_t ipv6_all_ones = { 	0xff, 0xff, 0xff, 0xff,
+						0xff, 0xff, 0xff, 0xff,
+						0xff, 0xff, 0xff, 0xff,
+						0xff, 0xff, 0xff, 0xff };
+
+	assert(asp->af == AF_INET6);
+	assert((prefixlen >= 0) && (prefixlen <= 128));
+
+	first = addr;
+	last = addr;
+	IP6_FIRST(&first, prefixlen);
+	IP6_LAST(&last, prefixlen);
+
+	/*
+	 * Search through the list linearly, looking for either:  an entry
+	 * contiguous to the one being added (with which we will merge) or a
+	 * discontiguous entry with a higher address (before which we will
+	 * insert).  If no match, we will append at the end.
+	 */
+	for (ptpn = &asp->head; (p = *ptpn) != NULL; ptpn = &p->next) {
+		temp = first;
+		IP6_DEC(&temp);
+		if (IP6_GT(&first, &ipv6_all_zeros) &&
+		    IP6_GT(&temp, &p->span.v6.last))
+			continue;
+		temp = last;
+		IP6_INC(&temp);
+		if (IP6_EQ(&last, &ipv6_all_ones) ||
+		    IP6_GE(&temp, &p->span.v6.first)) {
+			/* Merge with this entry. */
+			if (IP6_LT(&first, &p->span.v6.first))
+				p->span.v6.first = first;
+			while (IP6_GT(&last, &p->span.v6.last)) {
+				struct spannode *next = p->next;
+
+				if (next == NULL) {
+					p->span.v6.last = last;
+					break;
+				}
+
+				temp = next->span.v6.first;
+				IP6_DEC(&temp);
+				if (IP6_GE(&last, &temp)) {
+					/* Merge this span with the next. */
+					p->span.v6.last = next->span.v6.last;
+					p->next = next->next;
+					free(next);
+				} else {
+					p->span.v6.last = last;
+				}
+			}
+			return (0);
+		} else {
+			/* Found the insertion point; exit the loop. */
+			break;
+		}
+	}
+
+	/* ptpn now points to the "previous next" where we need to insert. */
+
+	p = malloc(sizeof (*p));
+	if (p == NULL)
+		return (1);
+	p->span.v6.first = first;
+	p->span.v6.last = last;
+	p->next = *ptpn;
+	*ptpn = p;
+
+	return (0);
+}
+
+/*
+ * Remove one range of IPv6 addresses from a set.
+ */
+static int
+addrset_delete_v6(struct addrset *asp, in6_addr_t first, in6_addr_t last)
+{
+	struct spannode **ptpn, *p;
+	in6_addr_t temp;
+
+	/*
+	 * Search through the list linearly, looking for any of:  an entry
+	 * entirely contained with the range being deleted (which we will
+	 * delete from the list) or an entry overlapping the first address of
+	 * the range (which we will truncate at its end) or an entry
+	 * overlapping the last address of the range (which we will truncate at
+	 * its beginning) or an entry which entirely contains the range being
+	 * deleted plus at least one address beyond in each direction (which we
+	 * will split into two entries) or an entry with a higher address than
+	 * we are deleting (at which point we are done).
+	 */
+	for (ptpn = &asp->head; (p = *ptpn) != NULL; ptpn = &p->next) {
+		if (IP6_GT(&p->span.v6.first, &last))
+			return (0);		/* all done */
+		if (IP6_LT(&p->span.v6.last, &first))
+			continue;	/* keep searching */
+		while (IP6_GE(&p->span.v6.first, &first) &&
+		    IP6_LE(&p->span.v6.last, &last)) {
+			/* Delete a span entirely. */
+			*ptpn = p->next;
+			free(p);
+			p = *ptpn;
+			if (p == NULL || IP6_GT(&p->span.v6.first, &last))
+				return (0);	/* all done */
+		}
+		if (IP6_GE(&p->span.v6.first, &first)) {
+			/* Truncate a span at its beginning. */
+			temp = last;
+			IP6_INC(&temp);
+			p->span.v6.first = temp;
+		} else if (IP6_LE(&p->span.v6.last, &last)) {
+			/* Truncate a span at its end. */
+			temp = first;
+			IP6_DEC(&temp);
+			p->span.v6.last = temp;
+		} else {
+			/* Split a span into two. */
+			struct spannode *p2 = malloc(sizeof (*p2));
+			if (p2 == NULL)
+				return (1);
+			temp = last;
+			IP6_INC(&temp);
+			p2->span.v6.first = temp;
+			p2->span.v6.last = p->span.v6.last;
+			p2->next = p->next;
+			temp = first;
+			IP6_DEC(&temp);
+			p->span.v6.last = temp;
+			p->next = p2;
+		}
+	}
+
+	return (0);
+}
+
+/*
+ * Compute the set difference (remove elements in set 2 from set 1).
+ */
+static void
+addrset_diff(struct addrset *asp1, struct addrset *asp2)
+{
+	struct spannode *p;
+
+	if (asp1->af != asp2->af)
+		return;
+
+	/* For each span in set 2, delete it from set 1. */
+	if (asp1->af == AF_INET)
+		for (p = asp2->head; p; p = p->next)
+			(void) addrset_delete_v4(asp1,
+			    p->span.v4.first, p->span.v4.last);
+	else if (asp1->af == AF_INET6)
+		for (p = asp2->head; p; p = p->next)
+			(void) addrset_delete_v6(asp1,
+			    p->span.v6.first, p->span.v6.last);
+}
+
+
+typedef struct mib_item_s {
+	int			group;
+	int			mib_id;
+	void			*valp;
+	size_t			length;
+} mib_item_t;
+
+static void	mibload(int sd);
+static void	mibfree(mib_item_t *item);
+static void	mib_get_constants(mib_item_t *item);
+
+static int ipRouteEntrySize;
+static int ipv6RouteEntrySize;
+
+static mib_item_t *ipv4Table;
+static mib_item_t *ipv6Table;
+
+/*
+ * Copy and NUL-terminate a MIB octet-string.
+ */
+static void
+octetstr(Octet_t *op, char *dst, uint_t dstlen)
+{
+	size_t n = MIN(dstlen - 1, op->o_length);
+	memcpy(dst, op->o_bytes, n);
+	dst[n] = '\0';
+}
+
+/*
+ * Read the whole IP MIB, looking for the routing related entries.
+ * Save the IPv4 and IPv6 route table items and peek into a couple other
+ * items to learn the increments between records in the route table items.
+ */
+static void
+mibload(int sd)
+{
+	/*
+	 * buf is an automatic for this function, so the
+	 * compiler has complete control over its alignment;
+	 * it is assumed this alignment is satisfactory for
+	 * it to be casted to certain other struct pointers
+	 * here, such as struct T_optmgmt_ack * .
+	 */
+	uintptr_t		buf[512 / sizeof (uintptr_t)];
+	int			flags;
+	int			j, getcode;
+	struct strbuf		ctlbuf, databuf;
+	struct T_optmgmt_req	*tor = (struct T_optmgmt_req *)buf;
+	struct T_optmgmt_ack	*toa = (struct T_optmgmt_ack *)buf;
+	struct T_error_ack	*tea = (struct T_error_ack *)buf;
+	struct opthdr		*req;
+	mib_item_t		*temp;
+
+	ipv4Table = NULL;
+	ipv6Table = NULL;
+
+	tor->PRIM_type = T_SVR4_OPTMGMT_REQ;
+	tor->OPT_offset = sizeof (struct T_optmgmt_req);
+	tor->OPT_length = sizeof (struct opthdr);
+	tor->MGMT_flags = T_CURRENT;
+	req = (struct opthdr *)&tor[1];
+	req->level = MIB2_IP;		/* any MIB2_xxx value ok here */
+	req->name  = 0;
+	req->len   = 0;
+
+	ctlbuf.buf = (char *)buf;
+	ctlbuf.len = tor->OPT_length + tor->OPT_offset;
+	flags = 0;
+	if (putmsg(sd, &ctlbuf, (struct strbuf *)0, flags) == -1) {
+		perror("mibget: putmsg(ctl) failed");
+		goto error_exit;
+	}
+
+	/*
+	 * Each reply consists of a ctl part for one fixed structure
+	 * or table, as defined in mib2.h.  The format is a T_OPTMGMT_ACK,
+	 * containing an opthdr structure.  level/name identify the entry,
+	 * len is the size of the data part of the message.
+	 */
+	req = (struct opthdr *)&toa[1];
+	ctlbuf.maxlen = sizeof (buf);
+	j = 1;
+	for (;;) {
+		flags = 0;
+		getcode = getmsg(sd, &ctlbuf, (struct strbuf *)0, &flags);
+		if (getcode == -1) {
+			perror("mibget getmsg(ctl) failed");
+			goto error_exit;
+		}
+		if (getcode == 0 &&
+		    ctlbuf.len >= sizeof (struct T_optmgmt_ack) &&
+		    toa->PRIM_type == T_OPTMGMT_ACK &&
+		    toa->MGMT_flags == T_SUCCESS &&
+		    req->len == 0)
+			return;
+
+		if (ctlbuf.len >= sizeof (struct T_error_ack) &&
+		    tea->PRIM_type == T_ERROR_ACK) {
+			(void) fprintf(stderr,
+			    "mibget %d gives T_ERROR_ACK: TLI_error = 0x%lx, "
+			    "UNIX_error = 0x%lx\n",
+			    j, tea->TLI_error, tea->UNIX_error);
+
+			errno = (tea->TLI_error == TSYSERR) ?
+			    tea->UNIX_error : EPROTO;
+			goto error_exit;
+		}
+
+		if (getcode != MOREDATA ||
+		    ctlbuf.len < sizeof (struct T_optmgmt_ack) ||
+		    toa->PRIM_type != T_OPTMGMT_ACK ||
+		    toa->MGMT_flags != T_SUCCESS) {
+			(void) printf("mibget getmsg(ctl) %d returned %d, "
+			    "ctlbuf.len = %d, PRIM_type = %ld\n",
+			    j, getcode, ctlbuf.len, toa->PRIM_type);
+
+			if (toa->PRIM_type == T_OPTMGMT_ACK)
+				(void) printf("T_OPTMGMT_ACK: "
+				    "MGMT_flags = 0x%lx, req->len = %ld\n",
+				    toa->MGMT_flags, req->len);
+			errno = ENOMSG;
+			goto error_exit;
+		}
+
+		temp = malloc(sizeof (mib_item_t));
+		if (temp == NULL) {
+			perror("mibget malloc failed");
+			goto error_exit;
+		}
+		temp->group = req->level;
+		temp->mib_id = req->name;
+		temp->length = req->len;
+		temp->valp = malloc(req->len);
+		if (temp->valp == NULL) {
+			free(temp);
+			goto error_exit;
+		}
+
+		databuf.maxlen = temp->length;
+		databuf.buf    = temp->valp;
+		databuf.len    = 0;
+		flags = 0;
+		getcode = getmsg(sd, (struct strbuf *)0, &databuf, &flags);
+		if (getcode == -1) {
+			perror("mibload getmsg(data) failed");
+			mibfree(temp);
+			goto error_exit;
+		} else if (getcode != 0) {
+			(void) printf("mibload getmsg(data) returned %d, "
+			    "databuf.maxlen = %d, databuf.len = %d\n",
+			    getcode, databuf.maxlen, databuf.len);
+			mibfree(temp);
+			goto error_exit;
+		}
+
+		j++;
+
+		if (temp->group != MIB2_IP &&
+		    temp->group != MIB2_IP6) {
+			mibfree(temp);
+			continue;
+		}
+
+		switch (temp->mib_id) {
+		case MIB2_IP_ROUTE:
+			if (ipv4Table)
+				mibfree(ipv4Table);
+			ipv4Table = temp;
+			break;
+		case MIB2_IP6_ROUTE:
+			if (ipv6Table)
+				mibfree(ipv6Table);
+			ipv6Table = temp;
+			break;
+		case 0:
+			mib_get_constants(temp);
+			/* FALLTHROUGH */
+		default:
+			mibfree(temp);
+			break;
+		}
+	}
+	/* NOTREACHED */
+
+error_exit:;
+}
+
+/*
+ * mibfree: frees a (mib_item_t *) loaded by mibload()
+ */
+static void
+mibfree(mib_item_t *item)
+{
+	if (item->valp != NULL)
+		free(item->valp);
+	free(item);
+}
+
+#define	IPROUTEENTRYALIGNMENT 4
+#define	IP6ROUTEENTRYALIGNMENT 4
+
+/* Extract constant sizes. */
+static void
+mib_get_constants(mib_item_t *item)
+{
+	switch (item->group) {
+	case MIB2_IP: {
+		mib2_ip_t *ip = item->valp;
+
+		ipRouteEntrySize = ip->ipRouteEntrySize;
+		assert(IS_P2ALIGNED(ipRouteEntrySize, IPROUTEENTRYALIGNMENT));
+		break;
+	}
+	case MIB2_IP6: {
+		mib2_ipv6IfStatsEntry_t *ip6 = item->valp;
+		/* Just use the first entry */
+
+		ipv6RouteEntrySize = ip6->ipv6RouteEntrySize;
+		assert(IS_P2ALIGNED(ipv6RouteEntrySize,
+		    IP6ROUTEENTRYALIGNMENT));
+		break;
+	}
+	}
+}
+
+
+/*
+ * Compose a PFILCMD_IFADDRSET message for each interface and deliver them to
+ * pfil.  Returns 0 for success, non-zero for failure.
+ */
+static int
+pfil_ifaddrset_msg(struct addrset **ifs, int numifs)
+{
+	int status = 0, i;
+	struct pfil_ifaddrset *ifaddrset = NULL;
+
+	for (i = 0; i < numifs; i++)
+		if (ifs[i]->af == AF_INET) {
+			struct spannode *p1;
+			struct pfil_v4span *p2;
+			int nspans = 0;
+			size_t size;
+
+			for (p1 = ifs[i]->head; p1; p1 = p1->next)
+				nspans++;
+			size = sizeof (struct pfil_ifaddrset) +
+			    nspans * sizeof (struct pfil_v4span);
+			ifaddrset = realloc(ifaddrset, size);
+			if (ifaddrset == NULL)
+				return (-1);
+
+			(void) strlcpy(ifaddrset->name, ifs[i]->name,
+			    LIFNAMSIZ);
+			ifaddrset->af = ifs[i]->af;
+			ifaddrset->nspans = nspans;
+			p2 = (struct pfil_v4span *)(ifaddrset + 1);
+			for (p1 = ifs[i]->head; p1; p1 = p1->next) {
+				p2->first = p1->span.v4.first;
+				p2->last = p1->span.v4.last;
+				++p2;
+			}
+
+			status = pfil_msg(PFILCMD_IFADDRSET, ifaddrset, size);
+			if (status != 0)
+				break;
+		} else if (ifs[i]->af == AF_INET6) {
+			struct spannode *p1;
+			struct pfil_v6span *p2;
+			int nspans = 0;
+			size_t size;
+
+			for (p1 = ifs[i]->head; p1; p1 = p1->next)
+				nspans++;
+			size = sizeof (struct pfil_ifaddrset) +
+			    nspans * sizeof (struct pfil_v6span);
+			ifaddrset = realloc(ifaddrset, size);
+			if (ifaddrset == NULL)
+				return (-1);
+
+			(void) strlcpy(ifaddrset->name, ifs[i]->name,
+			    LIFNAMSIZ);
+			ifaddrset->af = ifs[i]->af;
+			ifaddrset->nspans = nspans;
+			p2 = (struct pfil_v6span *)(ifaddrset + 1);
+			for (p1 = ifs[i]->head; p1; p1 = p1->next) {
+				p2->first = p1->span.v6.first;
+				p2->last = p1->span.v6.last;
+				++p2;
+			}
+
+			status = pfil_msg(PFILCMD_IFADDRSET, ifaddrset, size);
+			if (status != 0)
+				break;
+		}
+
+	if (ifaddrset != NULL)
+		free(ifaddrset);
+
+	return (status);
+}
+
+/*
+ * Find an interface through which the gateway is reachable and return its
+ * name in the specififed buffer.
+ */
+static void
+findgwif_v4(in_addr_t gw, char outif[], size_t size)
+{
+	mib2_ipRouteEntry_t *rp;
+
+	for (rp = ipv4Table->valp;
+	    (char *)rp < (char *)ipv4Table->valp + ipv4Table->length;
+	    rp = (mib2_ipRouteEntry_t *)
+	    ((char *)rp + ipRouteEntrySize)) {
+		if ((rp->ipRouteInfo.re_ire_type & IRE_INTERFACE) &&
+		    (rp->ipRouteIfIndex.o_length > 0) &&
+		    ((gw & rp->ipRouteMask) == rp->ipRouteDest)) {
+			octetstr(&rp->ipRouteIfIndex,
+			    outif, size);
+			return;
+		}
+	}
+	outif[0] = '\0';
+}
+
+/*
+ * Find an interface through which the gateway is reachable and return its
+ * name in the specififed buffer.
+ */
+static void
+findgwif_v6(in6_addr_t gw, char outif[], size_t size)
+{
+	mib2_ipv6RouteEntry_t *rp;
+	in6_addr_t temp;
+
+	for (rp = ipv6Table->valp;
+	    (char *)rp < (char *)ipv6Table->valp + ipv6Table->length;
+	    rp = (mib2_ipv6RouteEntry_t *)
+	    ((char *)rp + ipv6RouteEntrySize)) {
+		temp = gw;
+		IP6_FIRST(&temp, rp->ipv6RoutePfxLength);
+		if ((rp->ipv6RouteInfo.re_ire_type & IRE_INTERFACE) &&
+		    (rp->ipv6RouteIfIndex.o_length > 0) &&
+		    (IP6_EQ(&temp, &rp->ipv6RouteDest))) {
+			octetstr(&rp->ipv6RouteIfIndex,
+			    outif, size);
+			return;
+		}
+	}
+	outif[0] = '\0';
+}
+
+/*
+ * Compute the valid address sets for the specified interfaces, then compose a
+ * series of PFILCMD_IFADDRSET messages and deliver them to pfil.  Returns 0 for
+ * success, non-zero for failure.
+ */
+int
+vas(const struct pfil_ifaddrs *ifaddrlist, int numifs)
+{
+	const in6_addr_t ipv6_unspecified = IN6ADDR_ANY_INIT;
+	const in6_addr_t ipv6_loopback_addr = IN6ADDR_LOOPBACK_INIT;
+	const in6_addr_t ipv6_multi_addr = { 	0xffU, 0x00U, 0, 0,
+						0, 0, 0, 0,
+						0, 0, 0, 0,
+						0, 0, 0, 0 };
+
+	struct addrset **ifs = NULL, *illegal_v4 = NULL, *illegal_v6 = NULL;
+	int sd, i, status;
+
+	sd = open("/dev/arp", O_RDWR);
+	if (sd == -1)
+		return (-1);
+	mibload(sd);
+	(void) close(sd);
+
+	ifs = calloc(numifs, sizeof (*ifs));
+	if (ifs == NULL)
+		goto err;
+	for (i = 0; i < numifs; i++) {
+		/*
+		 * in.sin_family works for in6.sin6_family too.
+		 * Both are located in the same address.
+		 */
+		ifs[i] = new_addrset(ifaddrlist[i].name,
+		    ifaddrlist[i].localaddr.in.sin_family);
+		if (ifs[i] == NULL)
+			goto err;
+	}
+
+	illegal_v4 = new_addrset("[illegal]", AF_INET);
+	if (illegal_v4 == NULL)
+		goto err;
+
+	/* Multicast addresses are always illegal as source address. */
+	if (addrset_add_v4(illegal_v4,
+	    htonl(INADDR_UNSPEC_GROUP), htonl(IN_CLASSD_NET)))
+		goto err;
+
+	/* Loopback addresses are illegal on non-loopback interfaces. */
+	if (addrset_add_v4(illegal_v4,
+	    htonl(INADDR_LOOPBACK), htonl(IN_CLASSA_NET)))
+		goto err;
+
+	illegal_v6 = new_addrset("[illegal]", AF_INET6);
+	if (illegal_v6 == NULL)
+		goto err;
+
+	/* Multicast addresses are always illegal as source address. */
+	if (addrset_add_v6(illegal_v6, ipv6_multi_addr, 8))
+		goto err;
+
+	/* Loopback addresses are illegal on non-loopback interfaces. */
+	if (addrset_add_v6(illegal_v6, ipv6_loopback_addr, 128))
+		goto err;
+
+	/* Unspecified addresses are always illegal as source address. */
+	if (addrset_add_v6(illegal_v6, ipv6_unspecified, 128))
+		goto err;
+
+	if (ipRouteEntrySize < sizeof (mib2_ipRouteEntry_t) ||
+	    ipv6RouteEntrySize < sizeof (mib2_ipv6RouteEntry_t) ||
+	    (!ipv4Table && !ipv6Table)) {
+		errno = ENOENT;
+err:
+		status = -1;
+		goto done;
+	}
+
+	if (ipv4Table != NULL) {
+		mib2_ipRouteEntry_t *rp;
+
+		for (rp = ipv4Table->valp;
+		    (char *)rp < (char *)ipv4Table->valp + ipv4Table->length;
+		    rp = (mib2_ipRouteEntry_t *)
+		    ((char *)rp + ipRouteEntrySize)) {
+			struct addrset *asp = NULL;
+			char outif[LIFNAMSIZ + 1];
+
+			switch (rp->ipRouteInfo.re_ire_type) {
+			case IRE_CACHE:
+				continue;
+			case IRE_BROADCAST:
+			case IRE_LOCAL:
+				asp = illegal_v4;
+				break;
+			default:
+				if (rp->ipRouteIfIndex.o_length > 0) {
+					octetstr(&rp->ipRouteIfIndex,
+					    outif, sizeof (outif));
+				} else {
+					findgwif_v4(rp->ipRouteNextHop,
+					    outif, sizeof (outif));
+				}
+				if (outif[0] != '\0') {
+					for (i = 0; i < numifs; i++) {
+						if (ifs[i]->af == AF_INET &&
+						    strncmp(outif, ifs[i]->name,
+						    LIFNAMSIZ) == 0) {
+							asp = ifs[i];
+							break;
+						}
+					}
+				}
+				break;
+			}
+			if (asp != NULL &&
+			    addrset_add_v4(asp,
+			    rp->ipRouteDest, rp->ipRouteMask) != 0)
+				goto err;
+		}
+	}
+
+	if (ipv6Table != NULL) {
+		mib2_ipv6RouteEntry_t *rp;
+
+		for (rp = ipv6Table->valp;
+		    (char *)rp < (char *)ipv6Table->valp + ipv6Table->length;
+		    rp = (mib2_ipv6RouteEntry_t *)
+		    ((char *)rp + ipv6RouteEntrySize)) {
+			struct addrset *asp = NULL;
+			char outif[LIFNAMSIZ + 1];
+
+			switch (rp->ipv6RouteInfo.re_ire_type) {
+			case IRE_CACHE:
+				continue;
+			case IRE_BROADCAST:
+			case IRE_LOCAL:
+				asp = illegal_v6;
+				break;
+			default:
+				if (rp->ipv6RouteIfIndex.o_length > 0) {
+					octetstr(&rp->ipv6RouteIfIndex,
+					    outif, sizeof (outif));
+				} else {
+					findgwif_v6(rp->ipv6RouteNextHop,
+					    outif, sizeof (outif));
+				}
+				if (outif[0] != '\0') {
+					for (i = 0; i < numifs; i++) {
+						if (ifs[i]->af == AF_INET6 &&
+						    strncmp(outif, ifs[i]->name,
+						    LIFNAMSIZ) == 0) {
+							asp = ifs[i];
+							break;
+						}
+					}
+				}
+				break;
+			}
+			if (asp != NULL &&
+			    addrset_add_v6(asp, rp->ipv6RouteDest,
+			    rp->ipv6RoutePfxLength) != 0)
+				goto err;
+		}
+	}
+
+	for (i = 0; i < numifs; i++) {
+		if (ifs[i]->af == AF_INET)
+			addrset_diff(ifs[i], illegal_v4);
+		else if (ifs[i]->af == AF_INET6)
+			addrset_diff(ifs[i], illegal_v6);
+	}
+
+	status = pfil_ifaddrset_msg(ifs, numifs);
+#ifdef DEBUG
+	pfil_ifaddrset_msg(&illegal_v4, 1);
+	pfil_ifaddrset_msg(&illegal_v6, 1);
+#endif
+
+done:
+	if (ipv4Table != NULL)
+		mibfree(ipv4Table);
+	if (ipv6Table != NULL)
+		mibfree(ipv6Table);
+
+	for (i = 0; i < numifs; i++)
+		if (ifs[i] != NULL)
+			delete_addrset(ifs[i]);
+	free(ifs);
+	if (illegal_v4 != NULL)
+		delete_addrset(illegal_v4);
+	if (illegal_v6 != NULL)
+		delete_addrset(illegal_v6);
+
+	return (status);
+}
+
+#ifdef DEBUG
+static void
+fatal(int errcode, char *format, ...)
+{
+	va_list argp;
+
+	if (format == NULL)
+		return;
+
+	va_start(argp, format);
+	(void) vfprintf(stderr, format, argp);
+	va_end(argp);
+
+	exit(errcode);
+}
+
+static void
+pr_span(uint8_t af, const struct spannode *p, char *buf, size_t size)
+{
+	char buf1[INET6_ADDRSTRLEN], buf2[INET6_ADDRSTRLEN];
+
+	if (af == AF_INET) {
+		ipaddr_t addr;
+
+		addr = htonl(p->span.v4.first);
+		(void) inet_ntop(AF_INET, &addr, buf1, sizeof (buf1));
+
+		if (p->span.v4.first == p->span.v4.last) {
+			(void) strncpy(buf, buf1, size);
+		} else {
+			addr = htonl(p->span.v4.last);
+			(void) inet_ntop(AF_INET, &addr, buf2, sizeof (buf2));
+			(void) snprintf(buf, size, "%s - %s", buf1, buf2);
+		}
+	} else if (af == AF_INET6) {
+		in6_addr_t addr6;
+
+		addr6 = p->span.v6.first;
+		(void) inet_ntop(AF_INET6, &addr6, buf1, sizeof (buf1));
+
+		if (IP6_EQ(&p->span.v6.first, &p->span.v6.last)) {
+			(void) strncpy(buf, buf1, size);
+		} else {
+			addr6 = p->span.v6.last;
+			(void) inet_ntop(AF_INET6, &addr6, buf2, sizeof (buf2));
+			(void) snprintf(buf, size, "%s - %s", buf1, buf2);
+		}
+	}
+}
+
+static void
+pr_addrset(const struct addrset *asp)
+{
+	struct spannode *p;
+
+	(void) printf("addrset %s (%u):\n", asp->name, asp->af);
+
+	if (asp->head == 0) {
+		(void) puts(" [empty]");
+		return;
+	}
+
+	p = asp->head;
+	while (p != NULL) {
+		char buf[100];
+
+		(void) putchar(' ');
+		pr_span(asp->af, p, buf, sizeof (buf));
+		(void) fputs(buf, stdout);
+		if (p->next)
+			(void) putchar(',');
+		p = p->next;
+	}
+	(void) putchar('\n');
+}
+
+static void
+pr_ifaddrset(const struct pfil_ifaddrset *asp)
+{
+	int i;
+
+	(void) printf("addrset %s (%u):\n", asp->name, asp->af);
+
+	if (asp->nspans == 0) {
+		(void) puts(" [empty]");
+		return;
+	}
+
+	if (asp->af == AF_INET) {
+		struct pfil_v4span *p = (struct pfil_v4span *)(asp + 1);
+
+		for (i = 0; i < asp->nspans; i++) {
+			ipaddr_t addr;
+			char buf[INET_ADDRSTRLEN];
+
+			addr = htonl(p->first);
+			(void) inet_ntop(AF_INET, &addr, buf, sizeof (buf));
+			(void) printf(" %s", buf);
+
+			if (p->first != p->last) {
+				addr = htonl(p->last);
+				(void) inet_ntop(AF_INET, &addr,
+				    buf, sizeof (buf));
+				(void) printf(" - %s", buf);
+			}
+
+			if (i+1 < asp->nspans)
+				(void) putchar(',');
+			p++;
+		}
+		(void) putchar('\n');
+	} else if (asp->af == AF_INET6) {
+		struct pfil_v6span *p = (struct pfil_v6span *)(asp + 1);
+
+		for (i = 0; i < asp->nspans; i++) {
+			char buf[INET6_ADDRSTRLEN];
+
+			(void) inet_ntop(AF_INET6, &p->first,
+			    buf, sizeof (buf));
+			(void) printf(" %s", buf);
+
+			if (!IP6_EQ(&p->first, &p->last)) {
+				(void) inet_ntop(AF_INET6, &p->last,
+				    buf, sizeof (buf));
+				(void) printf(" - %s", buf);
+			}
+
+			if (i + 1 < asp->nspans)
+				(void) putchar(',');
+			p++;
+		}
+		(void) putchar('\n');
+	}
+}
+
+int
+pfil_msg(uint32_t cmd, void *buf, size_t len)
+{
+	struct pfil_ifaddrset *ifaddrset = buf;
+	pr_ifaddrset(ifaddrset);
+	return (0);
+}
+
+int
+main(int argc, char *argv[])
+{
+	int numifs, i;
+	struct pfil_ifaddrs *ifaddrlist;
+
+	numifs = argc-1;
+	if ((ifaddrlist = calloc(numifs, sizeof (ifaddrlist[0]))) == NULL)
+		return (-1);
+
+	for (i = 0; i < numifs; i++) {
+		(void) strlcpy(ifaddrlist[i].name, argv[i+1], LIFNAMSIZ);
+		ifaddrlist[i].localaddr.in.sin_family = AF_INET;
+	}
+
+	if (vas(ifaddrlist, numifs) != 0) {
+		free(ifaddrlist);
+		return (-1);
+	}
+
+	for (i = 0; i < numifs; i++) {
+		(void) strlcpy(ifaddrlist[i].name, argv[i+1], LIFNAMSIZ);
+		ifaddrlist[i].localaddr.in6.sin6_family = AF_INET6;
+	}
+	if (vas(ifaddrlist, numifs) != 0) {
+		free(ifaddrlist);
+		return (-1);
+	}
+
+	free(ifaddrlist);
+	return (0);
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/cmd/ipf/svc/pfil	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,43 @@
+#!/sbin/sh
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Autopush pfil on to filtering interfaces and restrict
+# network traffic during startup
+#
+
+
+PFILAP=/etc/ipf/pfil.ap
+
+case "$1" in
+'start')
+	/sbin/autopush -f ${PFILAP}
+	enabled=`svcprop -c -p general/enabled svc:/network/ipfilter:default`
+
+	# To avoid a window of vulnerability during the time that networking
+	# is being initialized but before the full ipf.conf configuration is
+	# loaded, install a temporary, restrictive rule set now, early in
+	# boot.  This gets replaced by the contents of ipf.conf when the
+	# svc:/network/ipfilter service is started.  Note that if /usr is not
+	# mounted, the window of vulnerability still exists because we can't
+	# run the ipf command this early.
+
+	if [ -x /usr/sbin/ipf ] && [ "$enabled" = "true" ]; then
+		echo "block in all" | /usr/sbin/ipf -Fa -f -
+		echo "block out all" | /usr/sbin/ipf -f -
+		echo "pass out from any to any port = 53 keep state" \
+		     | /usr/sbin/ipf -f -
+	fi
+	;;
+	
+*)
+	echo "Usage: $0 start"
+	exit 1
+	;;
+esac
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/cmd/ipf/svc/pfil.xml	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<!--
+	Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+	Use is subject to license terms.
+
+	ident	"%Z%%M%	%I%	%E% SMI"
+
+	NOTE:  This service manifest is not editable; its contents will
+	be overwritten by package or patch operations, including
+	operating system upgrade.  Make customizations in a different
+	file.
+
+	Service manifest for the pfil (packet filter) service.
+-->
+
+<service_bundle type='manifest' name='SUNWipfr:pfil'>
+
+<service
+	name='network/pfil'
+	type='service'
+	version='1'>
+
+	<create_default_instance enabled='true' />
+
+	<single_instance />
+
+	<dependent
+	    name='pfil_network'
+	    grouping='optional_all'
+	    restart_on='none'>
+		<service_fmri value='svc:/network/physical' />
+	</dependent>
+
+	<dependent
+	    name='pfil_sysid'
+	    grouping='optional_all'
+	    restart_on='none'>
+		<service_fmri value='svc:/system/sysidtool:net' />
+	</dependent>
+
+	<!--
+		The stop method really should deconfigure pfil from sad(7D),
+		but autopush(1M) doesn't have the ability to remove entries
+		based on a file in the same format as it uses to add them.
+	-->
+	<exec_method
+		type='method'
+		name='stop'
+		exec=':true'
+		timeout_seconds='0' >
+	</exec_method>
+
+	<exec_method
+		type='method'
+		name='start'
+		exec='/lib/svc/method/pfil start'
+		timeout_seconds='0' >
+	</exec_method>
+
+	<property_group
+		name='startd'
+		type='framework'>
+		<propval name='duration' type='astring' value='transient' />
+	</property_group>
+
+	<stability value='Unstable' />
+
+	<template>
+		<common_name>
+			<loctext xml:lang='C'>packet filter</loctext>
+		</common_name>
+		<description>
+			<loctext xml:lang='C'>
+			Packet filter interface; autopushes the pfil STREAMS
+			module on network devices.
+			</loctext>
+		</description>
+		<documentation>
+			<manpage title='ipfilter' section='5'
+				manpath='/usr/share/man' />
+		</documentation>
+	</template>
+</service>
+
+</service_bundle>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/uts/common/inet/pfil/compat.h	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#ifdef DEBUG
+# define	PFILDEBUG
+#endif
+
+#include "os.h"
+
+#ifndef	MTYPE
+# define	MTYPE(m)	((m)->b_datap->db_type)
+#endif
+
+#ifndef	MLEN
+# define	MLEN(m)		((m)->b_wptr - (m)->b_rptr)
+#endif
+
+#ifndef	MIN
+# define	MIN(a,b)	(((a)<(b))?(a):(b))
+#endif
+
+#ifndef ALIGN32
+# define	ALIGN32(x)      (x)
+#endif
+
+#ifdef  PFILDEBUG
+# define	PRINT(l,x)	do {if ((l) <= pfildebug) cmn_err x; } while (0)
+# define	QTONM(x)	(((x) && (x)->q_ptr) ? \
+				 ((qif_t *)(x)->q_ptr)->qf_name : "??")
+#else
+# define	PRINT(l,x)	;
+#endif
+
+#ifndef	LIFNAMSIZ
+# define	LIFNAMSIZ	32
+#endif
+
+#ifndef	ASSERT
+# define	ASSERT(x)
+#endif
+
+/*
+ * The list of SAPs below all come from Sun's <atm/iftypes.h> file.  It's not
+ * yet clear whether pfil should deal with any of these or not.
+ */
+#ifndef	IFMP_SAP
+# define	IFMP_SAP	0x0065
+#endif
+
+#ifndef	LANER_SAP
+# define	LANER_SAP	0x9999
+#endif
+
+#ifndef	SNMP_SAP
+# define	SNMP_SAP	0x999a
+#endif
+
+#ifndef	ILMI_SAP
+# define	ILMI_SAP	0x999b
+#endif
+
+#ifndef	SIG_SAP
+# define	SIG_SAP		0x999c
+#endif
+
+#ifndef	Q93B_MGMT_SAP
+# define	Q93B_MGMT_SAP	0x999d
+#endif
+
+#ifndef	UTIL_SAP
+# define	UTIL_SAP	0x999e
+#endif
+
+#ifndef	ERROR_SAP
+# define	ERROR_SAP	0x999f
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/uts/common/inet/pfil/ndd.c	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,442 @@
+/*
+ * Copyright (C) 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/types.h>
+#include <sys/cmn_err.h>
+#include <sys/stream.h>
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include "compat.h"
+#include "qif.h"
+#include "pfil.h"
+
+caddr_t	pfil_nd;
+
+#if !defined(sun) || SOLARIS2 <= 8
+static int qif_report(queue_t *, mblk_t *, caddr_t);
+static int sill_report(queue_t *, mblk_t *, caddr_t);
+static int qif_ipmp_report(queue_t *, mblk_t *, caddr_t);
+static int qif_ipmp_set(queue_t *, mblk_t *, char *, caddr_t);
+static int pfil_hl_set(queue_t *, mblk_t *, char *, caddr_t);
+
+extern int pfil_report(queue_t *, mblk_t *, caddr_t);
+#else
+static int qif_report(queue_t *, mblk_t *, caddr_t, cred_t *);
+static int sill_report(queue_t *, mblk_t *, caddr_t, cred_t *);
+static int qif_ipmp_report(queue_t *, mblk_t *, caddr_t, cred_t *);
+static int qif_ipmp_set(queue_t *, mblk_t *, char *, caddr_t , cred_t *);
+static int pfil_hl_set(queue_t *, mblk_t *, char *, caddr_t , cred_t *);
+
+extern int pfil_report(queue_t *, mblk_t *, caddr_t, cred_t *);
+#endif
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_nd_get                                                 */
+/* Returns:     int     - 0 == success                                      */
+/* Parameters:  q(I)    - pointer to queue                                  */
+/*              mp(I)   - pointer to mblk                                   */
+/*              ptr(I)  - pointer to value to retrieve                      */
+/*              cred(I) - pointer to credential information                 */
+/*                                                                          */
+/* Given a pointer "ptr" to some data to return, copy it into the mblk that */
+/* has been provided.                                                       */
+/* ------------------------------------------------------------------------ */
+#if !defined(sun) || SOLARIS2 <= 8
+/*ARGSUSED*/
+int pfil_nd_get(queue_t *q, mblk_t *mp, caddr_t ptr)
+#else
+/*ARGSUSED*/
+int pfil_nd_get(queue_t *q, mblk_t *mp, caddr_t ptr, cred_t *cred)
+#endif
+{
+	int *ip;
+
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(2,(CE_CONT, "pfil_nd_get(%p,%p,%p)\n",
+		 (void *)q, (void *)mp, (void *)ptr));
+	ip = (int *)ptr;
+	(void) mi_mpprintf(mp, "%d", *ip);
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_nd_set                                                 */
+/* Returns:     int     - 0 == success, > 0 error occurred                  */
+/* Parameters:  q(I)    - pointer to queue                                  */
+/*              mp(I)   - pointer to mblk                                   */
+/*              str(I)  - pointer to new value as a string                  */
+/*              ptr(I)  - pointer to value to be stored                     */
+/*              cred(I) - pointer to credential information                 */
+/*                                                                          */
+/* Given a pointer "ptr" to a location to store the new value represented   */
+/* by the string "str", check to see if we allow setting that variable and  */
+/* if the new value is within the definable ranges understood for it.       */
+/* ------------------------------------------------------------------------ */
+#if !defined(sun) || SOLARIS2 <= 8
+/*ARGSUSED*/
+int pfil_nd_set(queue_t *q, mblk_t *mp, char *str, caddr_t ptr)
+#else
+/*ARGSUSED*/
+int pfil_nd_set(queue_t *q, mblk_t *mp, char *str, caddr_t ptr, cred_t *cred)
+#endif
+{
+	char *end;
+	long i;
+
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(2, (CE_CONT, "pfil_nd_set(%p,%p,%s[%p],%p)\n", 
+		  (void *)q, (void *)mp, str, (void *)str, 
+		  (void *)ptr));
+
+#if (SOLARIS2 >= 10)
+	if (ddi_strtol(str, &end, 10, &i) != 0)
+		return (EINVAL);
+#else
+	i =  mi_strtol(str, &end, 10);
+#endif
+
+	if (ptr == (caddr_t)&pfildebug) {
+#ifdef	PFILDEBUG
+#if (SOLARIS2 >= 10)
+		if ((end == str) || (i < 0) || (i > 100))
+#else
+		if (i < 0 || i > 1)
+#endif
+#endif
+			return EINVAL;
+	} else if (ptr == (caddr_t)&qif_verbose) {
+		if ((end == str) || (i < 0) || (i > 1))
+			return EINVAL;
+	}
+	*((int *)ptr) = i;
+	return 0;
+}
+
+
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_ioctl_nd                                               */
+/* Returns:     int - B_TRUE == success, B_FALSE == getset error            */
+/* Parameters:  q(I)    - pointer to queue                                  */
+/*              mp(I)   - pointer to mblk                                   */
+/*                                                                          */
+/* Handle both incoming ndd set and get requests but only if they're not    */
+/* destined for another STREAMS module (ie. there is no next queue for this */
+/* message.)                                                                */
+/* ------------------------------------------------------------------------ */
+int pfil_ioctl_nd(queue_t *q, mblk_t *mp)
+{
+	return (nd_getset(q, pfil_nd, mp));
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_nd_init                                                */
+/* Returns:     int   - 0 == success, -1 == error                           */
+/* Parameters:  None.                                                       */
+/*                                                                          */
+/* Perform any initialisation required for processing ndd ioctl messages.   */
+/* ------------------------------------------------------------------------ */
+int pfil_nd_init()
+{
+
+#ifdef PFILDEBUG
+	if (!nd_load(&pfil_nd, "pfildebug", pfil_nd_get, pfil_nd_set,
+		      (caddr_t)&pfildebug)) {
+		nd_free(&pfil_nd);
+		return -1;
+	}
+#endif
+
+	if (!nd_load(&pfil_nd, "pfil_delayed_copy", pfil_nd_get, pfil_nd_set,
+		     (caddr_t)&pfil_delayed_copy)) {
+		nd_free(&pfil_nd);
+		return -1;
+	}
+
+	if (!nd_load(&pfil_nd, "pfil_interface", pfil_nd_get, NULL,
+		     (caddr_t)&pfilinterface)) {
+		nd_free(&pfil_nd);
+		return -1;
+	}
+
+	if (!nd_load(&pfil_nd, "qif_status", qif_report, NULL, NULL)) {
+		nd_free(&pfil_nd);
+		return -1;
+	}
+
+	if (!nd_load(&pfil_nd, "sill_status", sill_report, NULL, NULL)) {
+		nd_free(&pfil_nd);
+		return -1;
+	}
+
+	if (!nd_load(&pfil_nd, "qif_ipmp_status", qif_ipmp_report, NULL,
+		     NULL)) {
+		nd_free(&pfil_nd);
+		return -1;
+	}
+
+	if (!nd_load(&pfil_nd, "qif_ipmp_set", NULL, qif_ipmp_set, NULL)) {
+		nd_free(&pfil_nd);
+		return -1;
+	}
+
+	if (!nd_load(&pfil_nd, "qif_verbose", pfil_nd_get, pfil_nd_set,
+		     (caddr_t)&qif_verbose)) {
+		nd_free(&pfil_nd);
+		return -1;
+	}
+
+	if (!nd_load(&pfil_nd, "pfil_inet4", pfil_report, NULL,
+		     (void *)&pfh_inet4)) {
+		nd_free(&pfil_nd);
+		return -1;
+	}
+
+	if (!nd_load(&pfil_nd, "pfil_inet6", pfil_report, NULL,
+		     (void *)&pfh_inet6)) {
+		nd_free(&pfil_nd);
+		return -1;
+	}
+
+	if (!nd_load(&pfil_nd, "pfil_sync", pfil_report, NULL,
+		     (void *)&pfh_sync)) {
+		nd_free(&pfil_nd);
+		return -1;
+	}
+
+	if (!nd_load(&pfil_nd, "pfil_hl", NULL, pfil_hl_set, NULL)) {
+		nd_free(&pfil_nd);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_nd_fini                                                */
+/* Returns:     void                                                        */
+/* Parameters:  None.                                                       */
+/*                                                                          */
+/* Clean up any data structures related to ndd processing in preparation    */
+/* for the module being unloaded.                                           */
+/* ------------------------------------------------------------------------ */
+void pfil_nd_fini()
+{
+
+	nd_free(&pfil_nd);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    qif_report                                                  */
+/* Returns:     int                                                         */
+/* Parameters:  q(I)    - pointer to queue                                  */
+/*              mp(I)   - pointer to mblk                                   */
+/*              ptr(I)  - pointer to value to retrieve                      */
+/*              cred(I) - pointer to credential information                 */
+/*                                                                          */
+/* Fills the mblk with any qif data that happens to be currently available. */
+/* ------------------------------------------------------------------------ */
+#if !defined(sun) || SOLARIS2 <= 8
+/*ARGSUSED*/
+static int qif_report(queue_t *q, mblk_t *mp, caddr_t arg)
+#else
+/*ARGSUSED*/
+static int qif_report(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *cred)
+#endif
+{
+	qif_t *qif;
+
+	(void) mi_mpprintf(mp,
+		   "ifname ill q OTHERQ ipmp num sap hl nr nw bad copy copyfail drop notip nodata notdata");
+	READ_ENTER(&pfil_rw);
+	for (qif = qif_head ; qif; qif = qif->qf_next)
+		(void) mi_mpprintf(mp,
+			"%s %p %p %p %p %d %x %d %lu %lu %lu %lu %lu %lu %lu %lu %lu",
+				   qif->qf_name, (void *)qif->qf_ill,
+				   (void *)qif->qf_q, (void *)qif->qf_oq,
+				   (void *)qif->qf_ipmp, qif->qf_num,
+				   qif->qf_sap, (int)qif->qf_hl,
+				   qif->qf_nr, qif->qf_nw, qif->qf_bad,
+				   qif->qf_copy, qif->qf_copyfail,
+				   qif->qf_drop, qif->qf_notip,
+				   qif->qf_nodata, qif->qf_notdata);
+	RW_EXIT(&pfil_rw);
+	return 0;
+}
+
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    sill_report                                                 */
+/* Returns:     int                                                         */
+/* Parameters:  q(I)    - pointer to queue                                  */
+/*              mp(I)   - pointer to mblk                                   */
+/*              ptr(I)  - pointer to value to retrieve                      */
+/*              cred(I) - pointer to credential information                 */
+/*                                                                          */
+/* Fills the mblk with any shadow ill (s_illt) data that happens to be      */
+/* currently available.                                                     */
+/* ------------------------------------------------------------------------ */
+#if !defined(sun) || SOLARIS2 <= 8
+/*ARGSUSED*/
+static int sill_report(queue_t *q, mblk_t *mp, caddr_t arg)
+#else
+/*ARGSUSED*/
+static int sill_report(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *cred)
+#endif
+{
+	s_ill_t *sill;
+
+	(void) mi_mpprintf(mp,
+		   "sill name sap mtu localaddr netmask broadaddr dstaddr");
+	READ_ENTER(&pfil_rw);
+	for (sill = s_ill_g_head ; sill; sill = sill->ill_next)
+		(void) mi_mpprintf(mp, "%p %s %x %u %x %x %x %x",
+				   (void *)sill, sill->ill_name, sill->ill_sap,
+				   sill->mtu,
+				   sill->localaddr.in.sin_addr.s_addr,
+				   sill->netmask.in.sin_addr.s_addr,
+				   sill->broadaddr.in.sin_addr.s_addr,
+				   sill->dstaddr.in.sin_addr.s_addr);
+	RW_EXIT(&pfil_rw);
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    qif_ipmp_report                                             */
+/* Returns:     int                                                         */
+/* Parameters:  q(I)    - pointer to queue                                  */
+/*              mp(I)   - pointer to mblk                                   */
+/*              ptr(I)  - pointer to value to retrieve                      */
+/*              cred(I) - pointer to credential information                 */
+/*                                                                          */
+/* Fills the mblk with any qif data that happens to be currently available. */
+/* ------------------------------------------------------------------------ */
+#if !defined(sun) || SOLARIS2 <= 8
+/*ARGSUSED*/
+static int qif_ipmp_report(queue_t *q, mblk_t *mp, caddr_t arg)
+#else
+/*ARGSUSED*/
+static int qif_ipmp_report(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *cred)
+#endif
+{
+	qif_t *qif;
+
+	(void) mi_mpprintf(mp, "ifname members");
+	READ_ENTER(&pfil_rw);
+	for (qif = qif_head ; qif; qif = qif->qf_next) {
+		if ((qif->qf_flags & QF_IPMP) == 0)
+			continue;
+		(void) mi_mpprintf(mp, "%s %s", qif->qf_name, qif->qf_members);
+	}
+	RW_EXIT(&pfil_rw);
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    qif_ipmp_set                                                */
+/* Returns:     int     - 0 == success, > 0 error occurred                  */
+/* Parameters:  q(I)    - pointer to queue                                  */
+/*              mp(I)   - pointer to mblk                                   */
+/*              str(I)  - pointer to new value as a string                  */
+/*              ptr(I)  - pointer to value to be stored                     */
+/*              cred(I) - pointer to credential information                 */
+/*                                                                          */
+/* This function is a wrapper for qif_ipmp_update(), providing a run-time   */
+/* interactive way to configure the IPMP configuration for pfil without     */
+/* needing to load/unload the module to reread the config file (or is there */
+/* a way to do that once loaded, anyway?)                                   */
+/* ------------------------------------------------------------------------ */
+#if !defined(sun) || SOLARIS2 <= 8
+/*ARGSUSED*/
+static int qif_ipmp_set(queue_t *q, mblk_t *mp, char *str, caddr_t ptr)
+#else
+/*ARGSUSED*/
+static int qif_ipmp_set(queue_t *q, mblk_t *mp, char *str, caddr_t ptr,
+			cred_t *cred)
+#endif
+{
+	char *s, *t;
+
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(2, (CE_CONT, "qif_ipmp_set(0x%p,0x%p,0x%s[%p],0x%p)\n",
+		  (void *)q, (void *)mp, str, (void *)str, (void *)ptr));
+
+	t = NULL;
+	s = str;
+	do {
+		if (t != NULL)
+			s = t + 1;
+		t = strchr(s, ';');
+		if (t != NULL)
+			*t = '\0';
+		qif_ipmp_update(s);
+	} while (t != NULL);
+
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_hl_set                                                 */
+/* Returns:     int     - 0 == success, > 0 error occurred                  */
+/* Parameters:  q(I)    - pointer to queue                                  */
+/*              mp(I)   - pointer to mblk                                   */
+/*              str(I)  - pointer to new value as a string                  */
+/*              ptr(I)  - pointer to value to be stored                     */
+/*              cred(I) - pointer to credential information                 */
+/*                                                                          */
+/* Explicitly set the header length (hl) field of the qif structure.  This  */
+/* is used in situations where pfil cannot, for some reason, automatically  */
+/* determine it via either ioctl snooping or looking at passing messages.   */
+/* ndd -set /dev/pfil pfil_hl ipmp0=14  or v4:ipmp0=14                      */
+/* ------------------------------------------------------------------------ */
+#if !defined(sun) || SOLARIS2 <= 8
+/*ARGSUSED*/
+static int pfil_hl_set(queue_t *q, mblk_t *mp, char *str, caddr_t ptr)
+#else
+/*ARGSUSED*/
+static int pfil_hl_set(queue_t *q, mblk_t *mp, char *str, caddr_t ptr,
+			cred_t *cred)
+#endif
+{
+	char *s, *t;
+
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(2, (CE_CONT, "pfil_hl_set(0x%lx,0x%lx,0x%lx[%s],0x%lx)\n",
+		  (u_long)q, (u_long)mp, (u_long)str, str, (u_long)ptr));
+
+	t = NULL;
+	s = str;
+	do {
+		if (t != NULL)
+			s = t + 1;
+		t = strchr(s, ';');
+		if (t != NULL)
+			*t = '\0';
+		qif_hl_set(s);
+	} while (t != NULL);
+
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/uts/common/inet/pfil/os.h	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#include <sys/sunddi.h>
+#include <sys/ddi.h>
+#if SOLARIS2 >= 6
+# include <net/if_types.h>
+#endif
+#undef	IPOPT_EOL
+#undef	IPOPT_NOP
+#undef	IPOPT_LSRR
+#undef	IPOPT_RR
+#undef	IPOPT_SSRR
+
+#include <inet/common.h>
+#include <inet/mi.h>
+#include <inet/led.h>
+#include <inet/nd.h>
+#if SOLARIS2 >= 8
+# include <netinet/ip6.h>
+#endif
+#include <inet/ip.h>
+
+#define	MUTEX_ENTER(x)		mutex_enter(x)
+#define	MUTEX_EXIT(x)		mutex_exit(x)
+#define	READ_ENTER(x)		rw_enter(x, RW_READER)
+#define	WRITE_ENTER(x)		rw_enter(x, RW_WRITER)
+#define	RW_DOWNGRADE(x)		rw_downgrade(x)
+#define	RW_EXIT(x)		rw_exit(x)
+#define	KMALLOC(v,t,z,w)	(v) = (t)kmem_zalloc(z, w)
+#define	KMFREE(v, z)		kmem_free(v, z)
+
+extern	caddr_t			pfil_nd;
+
+#if defined(atomic_add_long) && (SOLARIS2 < 7)
+# undef atomic_add_long
+# define atomic_add_long(x,y)	atomic_add_32((uint32_t *)x, y)
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/uts/common/inet/pfil/pfil.c	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2000, 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * ident "@(#)$Id: pfil.c,v 1.27 2003/11/30 09:45:57 darrenr Exp $"
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef __hpux
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+#else
+struct uio;
+#endif
+
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/uio.h>
+#include <sys/buf.h>
+#include <sys/conf.h>
+#include <sys/cmn_err.h>
+#include <sys/stat.h>
+#include <sys/stream.h>
+#include <sys/poll.h>
+#include <sys/byteorder.h>
+#include <sys/socket.h>
+#ifdef sun
+# include <sys/kmem.h>
+#endif
+#include <sys/dlpi.h>
+#include <sys/lock.h>
+#include <sys/stropts.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#ifdef sun
+# include <inet/common.h>
+# if SOLARIS2 >= 8
+#  include <netinet/ip6.h>
+# endif
+# undef IPOPT_EOL
+# undef IPOPT_NOP
+# undef IPOPT_LSRR
+# undef IPOPT_SSRR
+# undef IPOPT_RR
+# include <inet/ip.h>
+#endif
+
+#include "compat.h"
+#include "qif.h"
+#include "pfil.h"
+
+
+int	pfil_delayed_copy = 1;
+int	pfilinterface = PFIL_INTERFACE;
+/*
+** HPUX Port
+** Align these structs to 16 bytes
+** so that the embedded locks (first member)
+** are 16 byte aligned
+*/
+#ifdef	__hpux
+#pragma align 16
+struct	pfil_head	pfh_inet4 = { 0, NULL, NULL, 0 };
+#pragma align 16
+struct	pfil_head	pfh_inet6 = { 0, NULL, NULL, 0 };
+#pragma align 16
+struct	pfil_head	pfh_sync = { 0, NULL, NULL, 0 };
+#else
+struct	pfil_head	pfh_inet4;
+struct	pfil_head	pfh_inet6;
+struct	pfil_head	pfh_sync;
+#endif
+
+
+static int pfil_list_add(pfil_list_t *,
+			 int (*) __P((struct ip *, int, void *, int,
+				      void *, mblk_t **)),
+			 int);
+static int pfil_list_remove(pfil_list_t *,
+			 int (*) __P((struct ip *, int, void *, int,
+				      void *, mblk_t **)));
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_report                                                 */
+/* Returns:     int     - always returns 0                                  */
+/* Parameters:  q(I)    - pointer to queue                                  */
+/*              mp(I)   - pointer to mblk                                   */
+/*              arg(I)  - pointer to value to retrieve                      */
+/*              cred(I) - pointer to credential information                 */
+/*                                                                          */
+/* Returns a list of the registered callbacks for processing packets going  */
+/* in and out on a particular filtering head structure                      */
+/* ------------------------------------------------------------------------ */
+#if !defined(sun) || (SOLARIS2 <= 8)
+/*ARGSUSED*/
+int pfil_report(queue_t *q, mblk_t *mp, caddr_t arg)
+#else
+/*ARGSUSED*/
+int pfil_report(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *cred)
+#endif
+{
+	packet_filter_hook_t *p;
+	pfil_head_t *ph;
+
+	ph = (pfil_head_t *)arg;
+
+	READ_ENTER(&ph->ph_lock);
+
+	(void) mi_mpprintf(mp, "in");
+	(void) mi_mpprintf(mp, "function\tflags");
+	for (p = ph->ph_in.pfl_top; p; p = p->pfil_next)
+		(void) mi_mpprintf(mp,"%p\t%x",
+				   (void *)p->pfil_func, p->pfil_flags);
+
+	(void) mi_mpprintf(mp, "out");
+	(void) mi_mpprintf(mp, "function\tflags");
+	for (p = ph->ph_out.pfl_top; p; p = p->pfil_next)
+		(void) mi_mpprintf(mp,"%p\t%x",
+				   (void *)p->pfil_func, p->pfil_flags);
+
+	RW_EXIT(&ph->ph_lock);
+
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_init                                                   */
+/* Returns:     void                                                        */
+/* Parameters:  ph(I) - pointer to pfil head structure                      */
+/*                                                                          */
+/* Initialise a pfil_head structure.                                        */
+/* ------------------------------------------------------------------------ */
+void
+pfil_init(ph)
+	 struct pfil_head *ph;
+{
+#ifdef sun
+	rw_init(&ph->ph_lock, "pfil head", RW_DRIVER, NULL);
+#endif
+#ifdef __hpux
+	initlock(&ph->ph_lock, PFIL_SMAJ, 1020, "pfil head");
+#endif
+	ph->ph_in.pfl_top = NULL;
+	ph->ph_in.pfl_tail = &ph->ph_in.pfl_top;
+	ph->ph_out.pfl_top = NULL;
+	ph->ph_out.pfl_tail = &ph->ph_out.pfl_top;
+	ph->ph_init = 1;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_add_hook                                               */
+/* Returns:     int      - 0 == success, else error.                        */
+/* Parameters:  func(I)  - function pointer to add                          */
+/*              flags(I) - flags describing for which events to call the    */
+/*                         passed function                                  */
+/*              ph(I)    - pointer to callback head structure               */
+/*                                                                          */
+/* This function is the public interface for adding a callback function to  */
+/* a list of callbacks for a particular protocol head (ph).                 */
+/*                                                                          */
+/* pfil_add_hook() adds a function to the packet filter hook.  the          */
+/* flags are:                                                               */
+/*	PFIL_IN		call me on incoming packets                         */
+/*	PFIL_OUT	call me on outgoing packets                         */
+/*	PFIL_WAITOK	OK to call malloc and wait whilst adding this hook  */
+/* ------------------------------------------------------------------------ */
+int
+pfil_add_hook(func, flags, ph)
+	int	(*func) __P((struct ip *, int, void *, int,
+			     void *, mblk_t **));
+	int	flags;
+	struct	pfil_head	*ph;
+{
+	int err = 0;
+
+	ASSERT((flags & ~(PFIL_IN|PFIL_OUT|PFIL_WAITOK)) == 0);
+
+	if (ph->ph_init == 0)
+		pfil_init(ph);
+
+	WRITE_ENTER(&ph->ph_lock);
+
+	if (flags & PFIL_IN)
+		err = pfil_list_add(&ph->ph_in, func, flags);
+
+	if ((err == 0) && (flags & PFIL_OUT))
+		err = pfil_list_add(&ph->ph_out, func, flags);
+
+	RW_EXIT(&ph->ph_lock);
+
+	return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_list_add                                               */
+/* Returns:     int      - 0 == success, else error.                        */
+/* Parameters:  list(I)  - pfil list pointer                                */
+/*              func(I)  - function pointer to add                          */
+/*              flags(I) - flags describing for which events to call the    */
+/*                         passed function                                  */
+/* Write Locks: list's owner                                                */
+/*                                                                          */
+/* Adds the function (func) to the end of the list of functions.            */
+/* ------------------------------------------------------------------------ */
+static int
+pfil_list_add(list, func, flags)
+	pfil_list_t *list;
+	int	(*func) __P((struct ip *, int, void *, int,
+			     void *, mblk_t **));
+	int flags;
+{
+	struct packet_filter_hook *pfh;
+	int wait;
+
+	for (pfh = list->pfl_top; pfh; pfh = pfh->pfil_next)
+		if (pfh->pfil_func == func)
+			return EEXIST;
+
+	wait = flags & PFIL_WAITOK ? KM_SLEEP : KM_NOSLEEP;
+
+	KMALLOC(pfh, struct packet_filter_hook *, sizeof(*pfh), wait);
+	if (pfh == NULL)
+		return ENOMEM;
+	pfh->pfil_func = func;
+	pfh->pfil_flags = flags;
+
+	/*
+	 * insert the input list in reverse order of the output list
+	 * so that the hooks are called in the reverse order for each
+	 * direction.  So if it was A,B,C for input, it is C,B,A for output.
+	 */
+
+	if (flags & PFIL_OUT) {
+		pfh->pfil_pnext = list->pfl_tail;
+		*list->pfl_tail = pfh;
+		list->pfl_tail = &pfh->pfil_next;
+	} else if (flags & PFIL_IN) {
+		pfh->pfil_pnext = &list->pfl_top;
+		pfh->pfil_next = list->pfl_top;
+		list->pfl_top = pfh;
+		if (pfh->pfil_next == NULL)
+			list->pfl_tail = &pfh->pfil_next;
+	}
+
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_remove_hook                                            */
+/* Returns:     int      - 0 == success, else error.                        */
+/* Parameters:  func(I)  - function pointer to remove                       */
+/*              flags(I) - flags describing for which events to call the    */
+/*                         passed function                                  */
+/*              ph(I)    - pointer to callback head structure               */
+/*                                                                          */
+/* pfil_remove_hook removes a specific function from a particular           */
+/* pfil_head's list of callbacks as given by which flags have been passed.  */
+/* ------------------------------------------------------------------------ */
+int
+pfil_remove_hook(func, flags, ph)
+	int	(*func) __P((struct ip *, int, void *, int,
+			     void *, mblk_t **));
+	int	flags;
+	struct	pfil_head	*ph;
+{
+	int err = 0;
+
+	ASSERT((flags & ~(PFIL_IN|PFIL_OUT)) == 0);
+
+	if (ph->ph_init == 0)
+		pfil_init(ph);
+
+	WRITE_ENTER(&ph->ph_lock);
+
+	if (flags & PFIL_IN)
+		err = pfil_list_remove(&ph->ph_in, func);
+
+	if ((err == 0) && (flags & PFIL_OUT))
+		err = pfil_list_remove(&ph->ph_out, func);
+
+	RW_EXIT(&ph->ph_lock);
+
+	return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_list_remove                                            */
+/* Returns:     int     - 0 == success, else error.                         */
+/* Parameters:  list(I) - pfil list pointer                                 */
+/*              func(I) - function pointer to remove                        */
+/* Write Locks: list's owner                                                */
+/*                                                                          */
+/* pfil_list_remove is an internal function that takes a function off the   */
+/* specified pfil list, providing that a match for func is found.           */
+/* ------------------------------------------------------------------------ */
+static int
+pfil_list_remove(list, func)
+	pfil_list_t *list;
+	int	(*func) __P((struct ip *, int, void *, int,
+			     void *, mblk_t **));
+{
+	struct packet_filter_hook *pfh;
+
+	for (pfh = list->pfl_top; pfh; pfh = pfh->pfil_next)
+		if (pfh->pfil_func == func) {
+			*pfh->pfil_pnext = pfh->pfil_next;
+			if (list->pfl_tail == &pfh->pfil_next)
+				list->pfl_tail = pfh->pfil_pnext;
+			KMFREE(pfh, sizeof(*pfh));
+			return 0;
+		}
+
+	return ESRCH;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_hook_get                                               */
+/* Returns:     struct packet_filter_hook * - pointer to first member in    */
+/*                                            list of callbacks or NULL if  */
+/*                                            if there are none.            */
+/* Parameters:  flags(I) - indicates which callback list to return          */ 
+/*              ph(I)    - pointer to callback head structure               */
+/* Locks:       READ(ph->ph_lock)                                           */
+/*                                                                          */
+/* Returns the first pointer of the list associated with "flags" or NULL if */
+/* flags is not a recognised value.                                         */
+/* ------------------------------------------------------------------------ */
+struct packet_filter_hook *
+pfil_hook_get(flag, ph)
+	int flag;
+	struct	pfil_head	*ph;
+{
+
+	/* ASSERT(rw_read_locked(&ph->ph_lock) != 0); */
+
+	if (ph->ph_init != 0) {
+		switch (flag)
+		{
+		case PFIL_IN:
+			return ph->ph_in.pfl_top;
+		case PFIL_OUT:
+			return ph->ph_out.pfl_top;
+		}
+	}
+	return NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/uts/common/inet/pfil/pfil.conf	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,28 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+
+name="pfil" parent="pseudo" instance=0;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/uts/common/inet/pfil/pfil.h	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifndef _NET_PFIL_H_
+#define _NET_PFIL_H_
+
+#define	PFIL_RELEASE	"2.1.6"
+#define	PFIL_VERSION	2010600
+#define	PFIL_INTERFACE	2000000
+
+#ifndef __P
+# ifdef __STDC__
+#  define	__P(x)	x
+# else
+#  define	__P(x)	()
+# endif
+#endif
+
+#ifdef sun
+# include <inet/ip.h>
+# if SOLARIS2 < 9
+#  include <netinet/in_systm.h>
+#  undef IPOPT_EOL
+#  undef IPOPT_NOP
+#  undef IPOPT_RR
+#  undef IPOPT_LSRR
+#  undef IPOPT_SSRR
+#  include <netinet/ip.h>
+# endif
+#endif
+#ifdef __hpux
+# include <netinet/in_systm.h>
+# include <netinet/in.h>
+# include <netinet/ip.h>
+#endif
+
+
+typedef	struct packet_filter_hook {
+	struct	packet_filter_hook *pfil_next;
+	struct	packet_filter_hook **pfil_pnext;
+	int	(*pfil_func) __P((struct ip *, int, void *, int,
+				  void *, mblk_t **));
+	int	pfil_flags;
+} packet_filter_hook_t;
+
+
+typedef	struct	pfil_list	{
+	struct	packet_filter_hook	*pfl_top;
+	struct	packet_filter_hook	**pfl_tail;
+} pfil_list_t;
+
+
+/*
+** HP Port
+** spinlocks should be the first member for
+** alignment reason. Spinlocks need to be 16 byte 
+** aligned. The struct itself is aligned during 
+** allocation so that the spinlock starts at a
+** 16 byte boundary
+*/
+typedef struct pfil_head {
+	krwlock_t	ph_lock;
+	pfil_list_t	ph_in;
+	pfil_list_t	ph_out;
+	int	ph_init;
+} pfil_head_t;
+
+
+#define	PFIL_IN		0x00000001
+#define	PFIL_OUT	0x00000002
+#define	PFIL_INOUT	(PFIL_IN|PFIL_OUT)
+#define	PFIL_WAITOK	0x00000004
+#define	PFIL_GROUP	0x00000008
+#define	PFIL_ALL	(PFIL_IN|PFIL_OUT)
+
+/* HPUX Port Major no. for pfil spinlocks */
+#define	PFIL_SMAJ	0
+
+void	pfil_init __P((struct pfil_head *));
+struct	packet_filter_hook *pfil_hook_get __P((int, struct pfil_head *));
+int	pfil_add_hook __P((int (*func) __P((struct ip *, int, void *, int,
+					    void *, mblk_t **)), int,
+			   struct pfil_head *));
+int	pfil_remove_hook __P((int (*func) __P((struct ip *, int, void *, int,
+					    void *, mblk_t **)), int,
+			   struct pfil_head *));
+int pfil_sendbuf(mblk_t *);
+mblk_t *pfil_make_dl_packet __P((mblk_t *, struct ip *, void *,
+				 char *, queue_t **));
+void pfil_send_dl_packet __P((queue_t *, mblk_t *));
+
+
+extern	int	pfilinterface;
+extern	int	pfil_delayed_copy;
+extern	int	pfildebug;
+extern	struct	pfil_head	pfh_inet4;	/* IPv4 packet processing */
+extern	struct	pfil_head	pfh_inet6;	/* IPv6 packet processing */
+extern	struct	pfil_head	pfh_sync;	/* Notification of interface */
+						/* naming/address changes.   */
+extern	krwlock_t	qif_rwlock;
+extern	krwlock_t	pfil_rw;
+
+/*
+ * NOTE: On Solaris, even though pfilwput(), etc, are prototyped as returning
+ * an int, the return value is never checked and much code ignores it, anyway,
+ * so for performance reasonsm, various functions return void instead of int.
+ */
+extern void pfilwput __P((queue_t *q, mblk_t *mp));
+extern void pfil_ioctl __P((queue_t *q, mblk_t *mp));
+extern int pfil_ioctl_nd __P((queue_t *q, mblk_t *mp));
+extern int pfil_nd_init __P((void));
+extern void pfil_nd_fini __P((void));
+extern int pfil_precheck __P((queue_t *, mblk_t **, int, struct qif *));
+extern void pfil_startup __P((void));
+extern void pfilmodrput __P((queue_t *q, mblk_t *mp));
+extern void pfilmodwput __P((queue_t *q, mblk_t *mp));
+extern void pfilmodwsrv __P((queue_t *q));
+#ifdef USE_SERVICE_ROUTINE
+extern int pfilmodrsrv __P((queue_t *q));
+#else
+#define pfilmodrsrv  NULL
+#endif
+
+#ifdef IRE_ILL_CN
+void pfil_addif(queue_t *, const char *, int);
+#endif
+
+extern void mb_copydata __P((mblk_t *, size_t , size_t, char *));
+extern void mb_copyback __P((mblk_t *, size_t , size_t, char *));
+extern int pfildebug;
+
+void pfil_update_ifaddr(mblk_t * mp);
+#endif /* _NET_PFIL_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/uts/common/inet/pfil/pfild.h	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+
+/*
+ * STREAMS control messages used to communicate between pfild and pfil.
+ * Messages are sent down to /dev/pfil as M_PROTO->M_DATA.
+ * M_PROTO block contains uint32_t command code.
+ * M_DATA block contains [an array of] the corresponding data structure.
+ */
+
+/*
+ * Data structure used to pass interface configuration information from
+ * pfild to the pfil kernel module.
+ */
+#define	PFILCMD_IFADDRS 1
+struct pfil_ifaddrs {
+	char name[LIFNAMSIZ];
+	union {
+		struct sockaddr_in in;
+		struct sockaddr_in6 in6;
+	} localaddr;
+	union {
+		struct sockaddr_in in;
+		struct sockaddr_in6 in6;
+	} netmask;
+	union {
+		struct sockaddr_in in;
+		struct sockaddr_in6 in6;
+	} broadaddr;
+	union {
+		struct sockaddr_in in;
+		struct sockaddr_in6 in6;
+	} dstaddr;
+	uint_t mtu;
+};
+
+/*
+ * Data structure used to pass interface valid source address set information
+ * from pfild to the pfil kernel module.
+ */
+#define	PFILCMD_IFADDRSET 2
+struct pfil_ifaddrset {
+	char name[LIFNAMSIZ];
+	uint8_t af;
+	uint32_t nspans;
+};
+struct pfil_v4span {
+	uint32_t first, last;		/* in host byte order! */
+};
+struct pfil_v6span {
+	struct in6_addr first, last;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/uts/common/inet/pfil/pfildrv.c	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,1171 @@
+/*
+ * Copyright (C) 2000, 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/conf.h>
+#include <sys/debug.h>
+#include <sys/atomic.h>
+#include <sys/ethernet.h>
+#include <sys/stream.h>
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/cred.h>
+#include <sys/modctl.h>
+#include <sys/devops.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/stat.h>
+#include <sys/cmn_err.h>
+#include <sys/dlpi.h>
+#include <sys/kmem.h>
+#include <sys/strsun.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <inet/common.h>
+#include <inet/nd.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/ip_icmp.h>
+#if SOLARIS2 >= 8
+# include <netinet/ip6.h>
+#endif
+#undef IPOPT_EOL
+#undef IPOPT_NOP
+#undef IPOPT_RR
+#undef IPOPT_LSRR
+#undef IPOPT_SSRR
+#include <inet/ip.h>
+#include <inet/ip_if.h>
+
+#include "compat.h"
+#include "qif.h"
+#include "pfil.h"
+
+
+#undef	USE_SERVICE_ROUTINE
+
+#define MINSDUSZ 1
+#define MAXSDUSZ INFPSZ
+
+char _depends_on[] = "drv/ip";
+
+static struct module_info pfil_minfo = {
+	0x534b, "pfil", MINSDUSZ, MAXSDUSZ, 0, 0
+};
+
+krwlock_t	pfil_rw;
+int		pfildebug = 0;
+int		pfil_installed = 0;
+
+#ifdef IRE_ILL_CN
+kmutex_t s_ill_g_head_lock;
+s_ill_t * s_ill_g_head = NULL;
+queue_t *pfildq;			/* pfild's read queue for packets */
+#endif
+
+/************************************************************************
+ * STREAMS device information (/dev/pfil)
+ */
+static int pfildevopen(queue_t *, dev_t *, int, int, cred_t *);
+static int pfildevclose(queue_t *, int, cred_t *);
+
+#ifdef IRE_ILL_CN
+static void pfil_remif(queue_t *q);
+static void _dump_s_ill(s_ill_t *);
+static void _dump_s_ill_all(void);
+#endif
+
+static struct qinit pfil_rinit = {
+	NULL, NULL, pfildevopen, pfildevclose, NULL, &pfil_minfo, NULL
+};
+
+static struct qinit pfil_winit = {
+	(pfi_t)pfilwput, NULL, NULL, NULL, NULL, &pfil_minfo, NULL
+};
+
+struct streamtab pfil_dev_strtab = {
+	&pfil_rinit, &pfil_winit
+};
+
+extern int nulldev();
+extern int nodev();
+
+void pfil_donotip(int, qif_t *, queue_t *, mblk_t *, mblk_t *, struct ip *, size_t);
+static int pfil_info(dev_info_t *, ddi_info_cmd_t , void *, void **);
+static int pfil_attach(dev_info_t *,  ddi_attach_cmd_t);
+#if SOLARIS2 < 10
+static int pfil_identify(dev_info_t *);
+#endif
+static int pfil_detach(dev_info_t *,  ddi_detach_cmd_t);
+
+#ifdef DDI_DEFINE_STREAM_OPS
+DDI_DEFINE_STREAM_OPS(pfil_devops, nulldev, nulldev, pfil_attach, pfil_detach,
+		      nulldev, pfil_info, D_MP, &pfil_dev_strtab);
+
+#else
+static struct cb_ops pfil_ops = {
+	nodev,		/* cb_open */
+	nodev,		/* cb_close */
+	nodev,		/* cb_strategy */
+	nodev,		/* cb_print */
+	nodev,		/* cb_dump */
+	nodev,		/* cb_read */
+	nodev,		/* cb_write */
+	nodev,		/* cb_ioctl */
+	nodev,		/* cb_devmap */
+	nodev,		/* cb_mmap */
+	nodev,		/* cb_segmap */
+	nochpoll,	/* cb_chpoll */
+	ddi_prop_op,	/* cb_prop_op */
+	&pfilinfo,	/* cb_stream */
+	D_MP		/* cb_flag */
+};
+
+static struct dev_ops pfil_devops = 
+{
+	DEVO_REV,	/* devo_rev */
+	0,		/* devo_refcnt */
+	pfil_info,	/* devo_getinfo */
+#if SOLARIS2 >= 10
+	nulldev,
+#else
+	pfil_identify,	/* devo_identify */
+#endif
+	nulldev,	/* devo_probe */
+	pfil_attach,	/* devo_attach */
+	pfil_detach,	/* devo_detach */
+	nodev,		/* devo_reset */
+	&pfil_ops,	/* devo_cb_ops */
+	NULL		/* devo_bus_ops */
+};
+#endif
+
+static struct modldrv modldrv = {
+	&mod_driverops, "pfil Streams driver "/**/PFIL_RELEASE, &pfil_devops
+};
+
+/************************************************************************
+ * STREAMS module information
+ */
+static int pfilmodopen(queue_t *, dev_t *, int, int, cred_t *);
+static int pfilmodclose(queue_t *, int, cred_t *);
+
+static struct qinit pfilmod_rinit = {
+	(pfi_t)pfilmodrput, NULL, pfilmodopen, pfilmodclose,
+	NULL, &pfil_minfo, NULL
+};
+
+static struct qinit pfilmod_winit = {
+	(pfi_t)pfilmodwput, NULL, NULL, NULL, NULL, &pfil_minfo, NULL
+};
+
+struct streamtab pfil_mod_strtab = {
+	&pfilmod_rinit, &pfilmod_winit
+};
+
+static struct fmodsw fsw = {
+	"pfil", &pfil_mod_strtab, D_MP
+};
+
+static struct modlstrmod modlstrmod = {
+	&mod_strmodops, "pfil Streams module "/**/PFIL_RELEASE,
+	&fsw
+};
+
+/************************************************************************
+ * STREAMS externally visible information for _init() and _info ()
+ */
+static struct modlinkage modlinkage = {
+	MODREV_1,
+	{ (void *)&modlstrmod, (void *)&modldrv, NULL }
+};
+
+/************************************************************************
+ * STREAMS device functions
+ */
+static dev_info_t *pfil_dev_info;
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_attach                                                 */
+/* Returns:     int     - DDI_SUCCESS for success, otherwise DDI_FAILURE    */
+/* Parameters:  devi(I) - pointer to packet information                     */
+/*              cmd(I)  - DDI command to process                            */
+/*                                                                          */
+/* Called when the driver has been attached, just create the device file.   */
+/* ------------------------------------------------------------------------ */
+/*ARGUSED*/
+static int pfil_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
+{
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(3,(CE_CONT, "!pfil_attach(%p,%x)\n", (void *)devi, cmd));
+
+	if (cmd != DDI_ATTACH)
+		return (DDI_FAILURE);
+
+	pfil_dev_info = devi;
+
+#if SOLARIS2 >= 8
+	return (ddi_create_minor_node(devi, "pfil", S_IFCHR, 0, DDI_PSEUDO, 0));
+#else
+	return (ddi_create_minor_node(devi, "pfil", S_IFCHR, 0, NULL, 0));
+#endif
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_detach                                                 */
+/* Returns:     int     - DDI_SUCCESS for success, otherwise DDI_FAILURE    */
+/* Parameters:  devi(I) - pointer to device information                     */
+/*              cmd(I)  - DDI command to process                            */
+/*                                                                          */
+/* Nothing to do here(?) except return that everything is ok.               */
+/* ------------------------------------------------------------------------ */
+/*ARGUSED*/
+static int pfil_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
+{
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(3,(CE_CONT, "!pfil_detach(%p,%x)\n", (void *)devi, cmd));
+
+	if (cmd != DDI_DETACH)
+		return (DDI_FAILURE);
+
+	ASSERT(devi == pfil_dev_info);
+
+	ddi_remove_minor_node(devi, NULL);
+	return (DDI_SUCCESS);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_info                                                   */
+/* Returns:     int - DDI_SUCCESS (success), DDI_FAILURE (failure)          */
+/* Parameters:  dip(I) - pointer to device information                      */
+/*              cmd(I) - DDI command to process                             */
+/*              arg(I) - paramter to the command to be processed            */
+/*              res(O) - pointer to storage for returning results           */
+/*                                                                          */
+/* Handles information queries made by the kernel of the STREAMS device.    */
+/* ------------------------------------------------------------------------ */
+/*ARGUSED*/
+static int pfil_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
+			 void **res)
+{
+	int result = DDI_FAILURE;
+
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(3,(CE_CONT, "!pfil_info(%p,%x,%p,%p)\n", (void *)dip, infocmd,
+		 arg, (void *)res));
+
+	switch (infocmd)
+	{
+	case DDI_INFO_DEVT2DEVINFO:
+		if (pfil_dev_info != NULL) {
+			*res = (void *)pfil_dev_info;
+			result = DDI_SUCCESS;
+		}
+		break;
+	case DDI_INFO_DEVT2INSTANCE:
+		*res = NULL;
+		result = DDI_SUCCESS;
+		break;
+	default :
+		break;
+	}
+	return result;
+}
+
+
+#if SOLARIS2 < 10
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_identify                                               */
+/* Returns:     int - DDI_IDENTIFIED (success), DDI_NOT_IDENTIFIED (failure)*/
+/* Parameters:  devi(I) -  pointer to a dev_info structure                  */
+/*                                                                          */
+/* Check to see if this module is correctly associated with the device info */
+/* structure passed in.                                                     */
+/* ------------------------------------------------------------------------ */
+static int pfil_identify(dev_info_t *devi)
+{
+	int result = DDI_NOT_IDENTIFIED;
+
+	/*LINTED: E_CONSTANT_CONDITION*/
+	PRINT(3,(CE_CONT, "!pfil_identify(%p)\n", (void *)devi));
+	if (strcmp((char *)ddi_get_name(devi), "!pfil") == 0)
+		result = DDI_IDENTIFIED;
+
+	return result;
+}
+#endif
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfildevopen                                                 */
+/* Returns:     int      - 0 == sucess, else failure                        */
+/* Parameters:  q(I)     - pointer to STREAMS queue                         */
+/*              devp(I)  - pointer to a device number                       */
+/*              oflag(I) - file mode open flags (always 0 for module opens) */
+/*              sflag(I) - flag indicating how the open is being made       */
+/*              crp(I)   - pointer to message credentials from the user     */
+/*                                                                          */
+/* Perform any action required to open the STREAMS device, supporting it    */
+/* being opened in a cloning fashion.                                       */
+/* ------------------------------------------------------------------------ */
+/*ARGSUSED*/
+static int pfildevopen(queue_t *q, dev_t *devp, int oflag, int sflag,
+		       cred_t *crp)
+{
+	int result = 0;
+
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(3,(CE_CONT, "!pfildevopen(%p,%p,%x,%x,%p) [%s]\n",
+		 (void *)q, (void *)devp, oflag, sflag, (void *)crp, QTONM(q)));
+	/*
+	 * As per recommendation on man page open(9e)
+	 */
+	if ((sflag & MODOPEN) != 0)
+		result = ENXIO;
+
+	if (result == 0)
+		qprocson(q);
+
+	return result;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfildevclose                                                */
+/* Returns:     int      - always returns 0.                                */
+/* Parameters:  q(I)     - pointer to STREAMS queue                         */
+/*              flag(I)  - file status flag                                 */
+/*              crp(I)   - pointer to message credentials from the user     */
+/*                                                                          */
+/* Perform any action required to close the STREAMS device.                 */
+/* ------------------------------------------------------------------------ */
+/*ARGSUSED*/
+static int pfildevclose(queue_t *q, int flag, cred_t *crp)
+{
+
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(3,(CE_CONT, "!pfildevclose(%p,%x,%p) [%s]\n",
+		 (void *)q, flag, (void *)crp, QTONM(q)));
+	qprocsoff(q);
+
+#ifdef IRE_ILL_CN
+	if (q == pfildq)
+		pfildq = NULL;
+#endif
+
+	return 0;
+}
+
+/************************************************************************
+ * STREAMS module functions
+ */
+/* ------------------------------------------------------------------------ */
+/* Function:    pfilmodopen                                                 */
+/* Returns:     int      - 0 == success, else error                         */
+/* Parameters:  q(I)     - pointer to read-side STREAMS queue               */
+/*              devp(I)  - pointer to a device number                       */
+/*              oflag(I) - file status open flags (always 0 for module open)*/
+/*              sflag(I) - flag indicating how the open is being made       */
+/*              crp(I)   - pointer to message credentials from the user     */
+/*                                                                          */
+/* open() entry hook for the STREAMS module.                                */
+/* ------------------------------------------------------------------------ */
+/*ARGSUSED*/
+static int pfilmodopen(queue_t *q, dev_t *devp, int oflag, int sflag,
+		       cred_t *crp)
+{
+
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(3,(CE_CONT, "!pfilmodopen(%p,%p,%x,%x,%p) [%s]\n",
+		 (void *)q, (void *)devp, oflag, sflag, (void *)crp, QTONM(q)));
+
+	/*
+	 * As per recommendation on man page open(9e)
+	 */
+	if (sflag != MODOPEN)
+		return ENXIO;
+
+	q->q_ptr = qif_new(q, KM_SLEEP);
+	WR(q)->q_ptr = q->q_ptr;
+	qprocson(q);
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfilmodclose                                                */
+/* Returns:     int     - always returns 0.                                 */
+/* Parameters:  q(I)    - pointer to read-side STREAMS queue                */
+/*              flag(I) - file status flag                                  */
+/*              crp(I)  - pointer to message credentials from the user      */
+/*                                                                          */
+/* close() entry hook for the STREAMS module. qif_delete() takes care of    */
+/* setting q_ptr back to NULL for both this and the write side queue.       */
+/* ------------------------------------------------------------------------ */
+/*ARGSUSED*/
+static int pfilmodclose(queue_t *q, int flag, cred_t *crp)
+{
+
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(3,(CE_CONT, "!pfilmodclose(%p,%x,%p) [%s]\n",
+		 (void *)q, flag, (void *)crp, QTONM(q)));
+
+	qprocsoff(q);
+
+#ifdef IRE_ILL_CN
+	pfil_remif(q);
+#endif
+	qif_delete(q->q_ptr, q);
+	return 0;
+}
+
+/************************************************************************
+ * other support functions
+ */
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_precheck                                               */
+/* Returns:     int - < 0 pass packet because it's not a type subject to    */
+/*                    firewall rules (i.e. internal STREAMS messages),      */
+/*                    0 == pass packet, else > 0 indicates passing          */
+/*                    prohibited (possibly due to an error occuring in      */
+/*                    this function.)                                       */
+/* Parameters:  q(I)   - pointer to STREAMS queue                           */
+/*              mp(I)  - pointer to STREAMS message                         */
+/*              qif(I) - pointer to per-queue interface information         */
+/* Locks:       pfil_rw                                                     */
+/*                                                                          */
+/* In here we attempt to determine if there is an IP packet within an mblk  */
+/* that is being passed along and if there is, ensure that it falls on a 32 */
+/* bit aligned address and at least all of the layer 3 header is in one     */
+/* buffer, preferably all the layer 4 too if we recognise it.  Finally, if  */
+/* we can be sure that the buffer passes some sanity checks, pass it on to  */
+/* the registered callbacks for the particular protocol/direction.          */
+/* ------------------------------------------------------------------------ */
+/*ARGSUSED*/
+int pfil_precheck(queue_t *q, mblk_t **mp, int flags, qif_t *qif)
+{
+	register struct ip *ip;
+	size_t hlen, len, off, mlen, iphlen, plen;
+	packet_filter_hook_t *pfh;
+	qpktinfo_t qpkt, *qpi;
+	struct pfil_head *ph;
+	mblk_t *m, *mt = *mp;
+	int err, out, sap;
+	u_char *bp;
+#if SOLARIS2 >= 8
+	ip6_t *ip6;
+#endif
+#ifndef	sparc
+	u_short __ipoff, __iplen;
+#endif
+
+	qpi = &qpkt;
+	qpi->qpi_q = q;
+	qpi->qpi_off = 0;
+	qpi->qpi_name = qif->qf_name;
+	qpi->qpi_real = qif;
+	qpi->qpi_ill = qif->qf_ill;
+	qpi->qpi_hl = qif->qf_hl;
+	qpi->qpi_ppa = qif->qf_ppa;
+	qpi->qpi_num = qif->qf_num;
+	qpi->qpi_flags = qif->qf_flags;
+	qpi->qpi_max_frag = qif->qf_max_frag;
+	if ((flags & PFIL_GROUP) != 0)
+		qpi->qpi_flags |= QF_GROUP;
+
+	/*
+	 * If there is only M_DATA for a packet going out, then any header
+	 * information (which would otherwise appear in an M_PROTO mblk before
+	 * the M_DATA) is prepended before the IP header.  We need to set the
+	 * offset to account for this.
+	 */
+	out = (flags & PFIL_OUT) ? 1 : 0;
+	off = (out) ? qpi->qpi_hl : 0;
+
+	ip = NULL;
+	m = NULL;
+#if SOLARIS2 >= 8
+	ip6 = NULL;
+#endif
+
+	/*
+	 * If the message protocol block indicates that there isn't a data
+	 * block following it, just return back.
+	 */
+	bp = (u_char *)ALIGN32(mt->b_rptr);
+
+	switch (MTYPE(mt))
+	{
+	case M_PROTO :
+	case M_PCPROTO :
+	    {
+		dl_unitdata_ind_t *dl = (dl_unitdata_ind_t *)bp;
+		if ((dl->dl_primitive != DL_UNITDATA_IND) &&
+		    (dl->dl_primitive != DL_UNITDATA_REQ)) {
+			ip = (struct ip *)dl;
+			if ((ip->ip_v == IPVERSION) &&
+			    (ip->ip_hl == (sizeof(*ip) >> 2)) &&
+			    (ntohs(ip->ip_len) == mt->b_wptr - mt->b_rptr)) {
+				off = 0;
+				m = mt;
+			} else {
+				atomic_add_long(&qif->qf_notdata, 1);
+				return -1;
+			}
+		} else {
+			m = mt->b_cont;
+			if (m == NULL) {
+				atomic_add_long(&qif->qf_nodata, 1);
+				return -3;	/* No data blocks */
+			}
+		}
+		break;
+	    }
+	case M_DATA :
+		m = mt;
+		break;
+	default :
+		atomic_add_long(&qif->qf_notdata, 1);
+		return -2;
+	}
+
+	/*
+	 * Find the first data block, count the data blocks in this chain and
+	 * the total amount of data.
+	 */
+	if (ip == NULL)
+		for (m = mt; m && (MTYPE(m) != M_DATA); m = m->b_cont)
+			off = 0;	/* Any non-M_DATA cancels the offset */
+
+	if (m == NULL) {
+		atomic_add_long(&qif->qf_nodata, 1);
+		return -3;	/* No data blocks */
+	}
+
+	/*
+	 * This is a complete kludge to try and work around some bizarre
+	 * packets which drop through into pfil_donotip.
+	 */
+	if ((mt != m) && (MTYPE(mt) == M_PROTO || MTYPE(mt) == M_PCPROTO)) {
+		dl_unitdata_ind_t *dl = (dl_unitdata_ind_t *)bp;
+
+		if ((dl->dl_primitive == DL_UNITDATA_IND) &&
+		    (dl->dl_group_address == 1)) {
+			qpi->qpi_flags |= QF_GROUP;
+			if (((*((u_char *)m->b_rptr) == 0x0) &&
+			    ((*((u_char *)m->b_rptr + 2) == 0x45))))
+				off += 2;
+		}
+
+	}
+
+	/*
+	 * We might have a 1st data block which is really M_PROTO, i.e. it is
+	 * only big enough for the link layer header
+	 */
+	while ((len = m->b_wptr - m->b_rptr) <= off) {
+		off -= len;
+		m = m->b_cont;
+		if (m == NULL) {
+			atomic_add_long(&qif->qf_nodata, 1);
+			return -4;	/* not enough data for IP */
+		}
+	}
+
+	ip = (struct ip *)(m->b_rptr + off);
+	len = m->b_wptr - m->b_rptr - off;
+	mlen = msgdsize(m);
+
+#ifdef IRE_ILL_CN
+	sap = ((s_ill_t *)qif->qf_ill)->ill_sap;
+#else
+	sap = ((ill_t *)qif->qf_ill)->ill_sap;
+#endif
+
+	if (mlen == 0)
+		mlen = m->b_wptr - m->b_rptr;
+	mlen -= off;
+
+#ifdef PFILDEBUG
+	/*LINTED: E_CONSTANT_CONDITION*/
+	PRINT(10,(CE_CONT,
+		  "!IP Filter[%s]: out %d len %ld/%ld sap %d ip %p b_rptr %p off %ld m %p/%d/%d/%p mt %p/%d/%d/%p\n",
+		  qif->qf_name, out, len, mlen, sap,
+		  (void *)ip, (void *)m->b_rptr, off, 
+		  (void *)m, MTYPE(m), (int)MLEN(m), (void *)m->b_cont,
+		  (void *)mt, MTYPE(mt), (int)MLEN(mt), (void *)mt->b_cont));
+#endif
+
+	/*
+	 * If there is more than one copy of this message traversing the
+	 * STREAMS stack (ie the packet is being used for snoop data), the
+	 * IP header isn't on a 32bit aligned address, or the IP header
+	 * isn't contain within a single block, then make a copy which
+	 * meets our requirements and do a freemsg on the one passed in
+	 * since we're no longer using it or passing it up.
+	 */
+
+	if ((pfil_delayed_copy == 0 && m->b_datap->db_ref > 1)
+	    || ((uintptr_t)ip & 0x3) || len < sizeof(*ip)
+	    || (sap != IP_DL_SAP
+#if SOLARIS2 >= 8
+		&& sap != IP6_DL_SAP
+#endif
+	        )) {
+		mblk_t *b;
+		mblk_t *nm;
+		mblk_t *nmt;
+		mblk_t *previous_nm;
+
+forced_copy:
+		nmt = NULL;
+		previous_nm = NULL;
+
+		/*
+		 * Duplicate the message block descriptors up to (and
+		 * including if the offset is non-zero) the block where
+		 * IP begins.
+		 */
+		for (b = mt; b != m || off; b = b->b_cont) {
+			nm = dupb(b);
+			if (nm == NULL) {
+				atomic_add_long(&qif->qf_copyfail, 1);
+				if (nmt)
+					freemsg(nmt);
+				return ENOBUFS;
+			}
+
+			nm->b_cont = NULL;
+			if (nmt)
+				linkb(previous_nm, nm);
+			else
+				nmt = nm;
+			previous_nm = nm;
+
+			/*
+			 * Set the length so the block only contains what
+			 * appears before IP.
+			 */
+			if (b == m) {
+				nm->b_wptr = nm->b_rptr + off;
+				break;
+			}
+		}
+
+		m->b_rptr += off;
+		nm = msgpullup(m, -1);
+		m->b_rptr -= off;
+
+		if (nm == NULL) {
+			atomic_add_long(&qif->qf_copyfail, 1);
+			if (nmt)
+				freemsg(nmt);
+			return ENOBUFS;
+		}
+
+		if (nmt)
+			linkb(previous_nm, nm);
+		else
+			nmt = nm;
+
+		freemsg(mt);
+
+		*mp = nmt;
+		mt = nmt;
+		m = nm;
+
+		ip = (struct ip *)m->b_rptr;
+		len = m->b_wptr - m->b_rptr;
+		mlen = len;
+		off = 0;
+	}
+
+	if (sap == IP_DL_SAP) {
+		u_short tlen;
+
+		hlen = sizeof(*ip);
+
+		/* XXX - might not be aligned (from ppp?) */
+		((char *)&tlen)[0] = ((char *)&ip->ip_len)[0];
+		((char *)&tlen)[1] = ((char *)&ip->ip_len)[1];
+		plen = ntohs(tlen);
+
+		ph = &pfh_inet4;
+	}
+#if SOLARIS2 >= 8
+	else if (sap == IP6_DL_SAP) {
+		u_short tlen;
+
+		hlen = sizeof(ip6_t);
+		ip6 = (ip6_t *)ip;
+
+		/* XXX - might not be aligned (from ppp?) */
+		((char *)&tlen)[0] = ((char *)&ip6->ip6_plen)[0];
+		((char *)&tlen)[1] = ((char *)&ip6->ip6_plen)[1];
+		plen = ntohs(tlen);
+		if (plen == 0)
+			return EMSGSIZE;	/* Jumbo gram */
+
+		ph = &pfh_inet6;
+	}
+#endif 
+	else {
+		sap = -1;
+	}
+
+	if (((sap == IP_DL_SAP) && (ip->ip_v != IPVERSION))
+#if SOLARIS2 >= 8
+	    || ((sap == IP6_DL_SAP) && (((ip6->ip6_vfc) & 0xf0) != 0x60))
+#endif
+	    || sap == -1
+	   ) {
+		atomic_add_long(&qif->qf_notip, 1);
+#ifdef PFILDEBUG
+		pfil_donotip(out, qif, q, m, mt, ip, off);
+#endif
+		return EINVAL;
+	}
+
+	if (sap == IP_DL_SAP)
+		iphlen = ip->ip_hl << 2;
+#if SOLARIS2 >= 8
+	else if (sap == IP6_DL_SAP)
+		iphlen = sizeof(ip6_t);
+#endif
+
+	if ((
+#if SOLARIS2 >= 8
+	     (sap == IP6_DL_SAP) && (mlen < plen)) ||
+	    ((sap == IP_DL_SAP) &&
+#endif 
+	     ((iphlen < hlen) || (iphlen > plen) || (mlen < plen)))) {
+		/*
+		 * Bad IP packet or not enough data/data length mismatches
+		 */
+		atomic_add_long(&qif->qf_bad, 1);
+		return EINVAL;
+	}
+
+	/*
+	 * If we don't have enough data in the mblk or we haven't yet copied
+	 * enough (above), then copy some more.
+	 */
+	if ((iphlen > len)) {
+		if (m->b_datap->db_ref > 1)
+			goto forced_copy;
+		if (!pullupmsg(m, (int)iphlen + off)) {
+			atomic_add_long(&qif->qf_nodata, 1);
+			return ENOBUFS;
+		}
+		ip = (struct ip *)ALIGN32(m->b_rptr + off);
+	}
+
+	/*
+	 * Discard any excess data.
+	 */
+	if (sap == IP6_DL_SAP && len > iphlen + plen)
+		m->b_wptr = m->b_rptr + off + plen + iphlen;
+	else if (sap == IP_DL_SAP && len > plen)
+		m->b_wptr = m->b_rptr + off + plen;
+
+	/*
+	 * The code in IPFilter assumes that both the ip_off and ip_len
+	 * fields are in host byte order, so convert them here to fulfill
+	 * that expectation.
+	 *
+	 * If the target compile host is non-SPARC, assume it is a little
+	 * endian machine, requiring the conversion of offset/length fields
+	 * to both be host byte ordered.
+	 */
+#ifndef sparc
+	if (sap == IP_DL_SAP) {
+		__ipoff = (u_short)ip->ip_off;
+		ip->ip_len = plen;
+		ip->ip_off = ntohs(__ipoff);
+	}
+#endif
+
+	qpi->qpi_m = m;
+	qpi->qpi_off = off;
+	qpi->qpi_data = ip;
+
+	if (qif->qf_ipmp != NULL)
+		qif = qif->qf_ipmp;
+
+	READ_ENTER(&ph->ph_lock);
+
+	pfh = pfil_hook_get(flags & PFIL_INOUT, ph);
+	err = 0;
+
+	/*LINTED: E_CONSTANT_CONDITION*/
+	PRINT(8,(CE_CONT, "!pfil_hook_get(%x,%p) = %p\n",
+		 flags, (void *)ph, (void *)pfh));
+	for (; pfh; pfh = pfh->pfil_next)
+		if (pfh->pfil_func) {
+			err = (*pfh->pfil_func)(ip, iphlen, qif, out, qpi, mp);
+			if (err || !*mp)
+				break;
+			/*
+			 * fr_pullup may have allocated a new buffer.
+			 */
+			ip = qpi->qpi_data;
+		}
+	RW_EXIT(&ph->ph_lock);
+
+	/*
+	 * Functions called via pfil_func should only return values >= 0, so
+	 * convert any that are < 0 to be > 0 and preserve the absolute value.
+	 */
+	if (err < 0)
+		err = -err;
+
+	/*
+	 * If we still have a STREAMS message after calling the filtering
+	 * hooks, return the byte order of the fields changed above on
+	 * platforms where this is required.  They are refetched from the
+	 * packet headers because the callback (pfil_func) may have changed
+	 * them in some way.
+	 */
+#ifndef sparc
+	if ((err == 0) && (*mp != NULL)) {
+		if (sap == IP_DL_SAP) {
+			__iplen = (u_short)ip->ip_len;
+			__ipoff = (u_short)ip->ip_off;
+			ip->ip_len = htons(__iplen);
+			ip->ip_off = htons(__ipoff);
+		}
+	}
+#endif
+	return err;
+}
+
+
+/************************************************************************
+ * kernel module initialization
+ */
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    _init                                                       */
+/* Returns:     int - DDI_SUCCESS == success, else failure                  */
+/* Parameters:  Nil.                                                        */
+/*                                                                          */
+/* Initialise the kernel module and if that succeeds, call other init       */
+/* routines, elsewhere, that handle initialisation of the more generic      */
+/* components.                                                              */
+/* ------------------------------------------------------------------------ */
+int _init(void)
+{
+	int result;
+
+	result = pfil_nd_init();
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(2,(CE_CONT, "pfil_nd_init():%d\n", result));
+	if (result != 0)
+		return DDI_FAILURE;
+
+	if (qif_startup() == -1)
+		return DDI_FAILURE;
+
+	rw_init(&pfil_rw, "pfil_rw", RW_DRIVER, 0);
+#ifdef IRE_ILL_CN
+	mutex_init(&s_ill_g_head_lock, NULL, MUTEX_DRIVER, NULL);
+#endif
+	pfil_startup();
+
+	result = mod_install(&modlinkage);
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(1,(CE_CONT, "_init():%d\n", result));
+
+	return result;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    _fini                                                       */
+/* Returns:     int - DDI_SUCCESS == success, else failure                  */
+/* Parameters:  Nil.                                                        */
+/*                                                                          */
+/* Called when the OS attempts to unload the module, it should only be      */
+/* allowed to succeed if pfil is not currently in the middle of any STREAMS */
+/* "connections".  If it isn't then turn ourselves off and remove the module*/
+/* ------------------------------------------------------------------------ */
+int _fini(void)
+{
+	int result;
+
+	if (qif_head != NULL)
+		return EBUSY;
+	result = mod_remove(&modlinkage);
+
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(1,(CE_CONT, "_fini():%d\n", result));
+
+	if (result == DDI_SUCCESS) {
+		pfil_nd_fini();
+		qif_stop();
+#ifdef IRE_ILL_CN
+		mutex_destroy(&s_ill_g_head_lock);
+#endif
+		pfil_installed = 0;
+	}
+	return result;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    _info                                                       */
+/* Returns:     int - DDI_SUCCESS == success, else failure                  */
+/* Parameters:  modinfop(I) - pointer to module informatio buffer           */
+/*                                                                          */
+/* Standard _info() implementation that just calls mod_info on its linkage  */
+/* structure so information can be copied back into the modinfop struct.    */
+/* ------------------------------------------------------------------------ */
+int _info(struct modinfo *modinfop)
+{
+	int result;
+
+	result = mod_info(&modlinkage, modinfop);
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(3,(CE_CONT, "_info(%p):%x\n", (void *)modinfop, result));
+	return result;
+}
+
+
+/************************************************************************
+ * Sun Solaris ON build specific routines follow here.
+ */
+#ifdef IRE_ILL_CN
+static void _dump_s_ill(s_ill_t *ts)
+{
+	cmn_err(CE_NOTE, "s_ill next = 0x%p", (void *)ts->ill_next);
+	cmn_err(CE_NOTE, "s_ill sap = 0x%x", ts->ill_sap);
+	cmn_err(CE_NOTE, "s_ill name = %s", ts->ill_name);
+	cmn_err(CE_NOTE, "s_ill rq = 0x%p", (void *)ts->ill_rq);
+}
+
+static void
+_dump_s_ill_all(void)
+{
+	s_ill_t *ill;
+	/* who care locks */
+	if (pfildebug > 10) {
+		cmn_err(CE_NOTE, "s_ill_g_head = 0x%p\n", (void *)s_ill_g_head);
+		for (ill = s_ill_g_head; ill; ill = ill->ill_next) {
+			_dump_s_ill(ill);
+		}
+		cmn_err(CE_NOTE, "s_ill_g_head done\n");
+	}
+}
+
+
+/*
+ * Allocate an s_ill_t for this interface (name) if needed.
+ * Populate the read queue pointer.
+ */
+void pfil_addif(queue_t *rq, const char *name, int sap)
+{
+	s_ill_t *ill;
+
+	mutex_enter(&s_ill_g_head_lock);
+
+	/* XXX: Need to check for duplicate */
+	/* If replumbed, rq will be updated */
+	for (ill = s_ill_g_head; ill; ill = ill->ill_next) {
+
+		if (ill->ill_sap == sap &&
+		    strncmp(name, ill->ill_name, LIFNAMSIZ) == 0) {
+		  /* interface already there */
+			break;
+		}
+	}
+
+	if (!ill) {
+		ill = kmem_zalloc(sizeof(s_ill_t), KM_NOSLEEP);
+		if (!ill) {
+			cmn_err(CE_NOTE, "PFIL: malloc(%d) for ill failed",
+			(int)sizeof(s_ill_t));
+			mutex_exit(&s_ill_g_head_lock);
+			return;
+		}
+		ill->ill_sap = sap;
+		(void) strncpy(ill->ill_name, name, LIFNAMSIZ);
+		ill->ill_name[sizeof(ill->ill_name) - 1] = '\0';
+		ill->ill_next = s_ill_g_head;
+		s_ill_g_head = ill;
+	}
+
+	ASSERT(ill != NULL);
+	ill->ill_rq = rq;
+	_dump_s_ill_all();
+	mutex_exit(&s_ill_g_head_lock);
+}
+
+
+/*
+ * Deactivate any s_ill_t for this interface (queue pair).
+ * Called when a module is being closed (popped).
+ */
+static void pfil_remif(queue_t *rq)
+{
+	s_ill_t *ill;
+
+	WRITE_ENTER(&pfil_rw);
+	mutex_enter(&s_ill_g_head_lock);
+
+	for (ill = s_ill_g_head; ill; ill = ill->ill_next)
+		if (ill->ill_rq == rq)
+			ill->ill_rq = 0;
+	_dump_s_ill_all();
+	mutex_exit(&s_ill_g_head_lock);
+	RW_EXIT(&pfil_rw);
+}
+#endif /* IRE_ILL_CN */
+
+
+/************************************************************************
+ *
+ */
+#ifdef PFILDEBUG
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_donotip                                                */
+/* Returns:     Nil                                                         */
+/* Parameters:  out(I) - in(0)/out(1) flag for direction of message         */
+/*              qif(I) - pointer to per-queue interface information         */
+/*              q(I)   - pointer to STREAMS queue                           */
+/*              m(I)   - pointer to STREAMS message block where IP starts   */
+/*              mt(I)  - pointer to the start of the STREAMS message        */
+/*              ip(I)  - pointer to the start of the IP header              */
+/*              off(I) - offset from start of message to start of IP header */
+/*                                                                          */
+/* This function is here solely for dumping out the contents of an mblk and */
+/* showing what related information is known about it, to aid in debugging  */
+/* processing of messages going by that fail to be recognised properly.     */
+/* ------------------------------------------------------------------------ */
+void pfil_donotip(int out, qif_t *qif, queue_t *q, mblk_t *m, mblk_t *mt, struct ip *ip, size_t off)
+{
+	u_char *s, outb[256], *t;
+	int i;
+
+	outb[0] = '\0';
+	outb[1] = '\0';
+	outb[2] = '\0';
+	outb[3] = '\0';
+	s = ip ? (u_char *)ip : outb;
+	if (!ip && (m == mt) && m->b_cont && (MTYPE(m) != M_DATA))
+		m = m->b_cont;
+
+	/*LINTED: E_CONSTANT_CONDITION*/
+	PRINT(9,(CE_CONT, 
+		 "!IP %s:%d %ld %p %p %p ip %p b_rptr %p off %ld m %p/%d/%d/%p mt %p/%d/%d/%p\n",
+		  qif ? qif->qf_name : "?", out, qif ? qif->qf_hl : -1, 
+		  (void *)q, q ? q->q_ptr : NULL, q ? (void *)q->q_qinfo : NULL,
+		  (void *)ip, (void *)m->b_rptr, off, 
+		  (void *)m, MTYPE(m), (int)MLEN(m), (void *)m->b_cont,
+		  (void *)mt, MTYPE(mt), (int)MLEN(mt), (void *)mt->b_cont));
+	/*LINTED: E_CONSTANT_CONDITION*/
+	PRINT(9,(CE_CONT, "%02x%02x%02x%02x\n", *s, *(s+1), *(s+2), *(s+3)));
+	while (m != mt) {
+		i = 0;
+		t = outb;
+
+		s = mt->b_rptr;
+		(void)sprintf((char *)t, "%d:", MTYPE(mt));
+		t += strlen((char *)t);
+		for (; (i < 100) && (s < mt->b_wptr); i++) {
+			(void)sprintf((char *)t, "%02x%s", *s++,
+				((i & 3) == 3) ? " " : "");
+			t += ((i & 3) == 3) ? 3 : 2;
+		}
+		*t++ = '\n';
+		*t = '\0';
+		/*LINTED: E_CONSTANT_CONDITION*/
+		PRINT(50,(CE_CONT, "%s", outb));
+		mt = mt->b_cont;
+	}
+	i = 0;
+	t = outb;
+	s = m->b_rptr;
+	(void)sprintf((char *)t, "%d:", MTYPE(m));
+	t += strlen((char *)t);
+	for (; (i < 100) && (s < m->b_wptr); i++) {
+		(void)sprintf((char *)t, "%02x%s", *s++,
+			      ((i & 3) == 3) ? " " : "");
+		t += ((i & 3) == 3) ? 3 : 2;
+	}
+	*t++ = '\n';
+	*t = '\0';
+	/*LINTED: E_CONSTANT_CONDITION*/
+	PRINT(50,(CE_CONT, "%s", outb));
+}
+#endif
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_property_update                                        */
+/* Returns:     int - DDI_SUCCESS == success, else failure                  */
+/* Parameters:  modinfop(I) - pointer to module informatio buffer           */
+/*                                                                          */
+/* Fetch configuration file values that have been entered into the          */
+/* pfil.conf driver file.                                                   */
+/* ------------------------------------------------------------------------ */
+static int pfil_property_update(dev_info_t *dip)
+{
+	char *list, *s, *t;
+	int err;
+
+	if (ddi_prop_update_int(DDI_DEV_T_ANY, dip,
+				"ddi-no-autodetach", 1) == -1) {
+		cmn_err(CE_WARN, "!updating ddi-no-authdetach failed");
+		return DDI_FAILURE;
+	}
+
+	list = NULL;
+	err = ddi_prop_lookup_string(DDI_DEV_T_ANY, dip,
+				     0, "qif_ipmp_set", &list);
+#ifdef	IPFDEBUG
+	cmn_err(CE_CONT, "IP Filter: lookup_string(pfil_ipmp_list) = %d\n",
+		err);
+#endif
+	if (err == DDI_SUCCESS) {
+		t = NULL;
+		s = list;
+		do {
+			if (t != NULL)
+				s = t + 1;
+			t = strchr(s, ';');
+			if (t != NULL)
+				*t = '\0';
+			qif_ipmp_update(s);
+		} while (t != NULL);
+
+		ddi_prop_free(list);
+	}
+
+	return DDI_SUCCESS;
+}
+
+
+#if SOLARIS2 == 8
+int miocpullup(mblk_t *m, size_t len)
+{
+	if (m->b_cont == NULL)
+		return 0;
+	return pullupmsg(m->b_cont, len);
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/uts/common/inet/pfil/pfilstream.c	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,761 @@
+/*
+ * Copyright (C) 2000, 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+struct uio;
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <sys/stream.h>
+#ifdef HPUX_1111
+# include <sys/cred.h>
+#endif
+#include <sys/dlpi.h>
+#include <sys/cmn_err.h>
+#ifdef sun
+# include <sys/atomic.h>
+# include <sys/sockio.h>
+# include <sys/ksynch.h>
+# include <sys/strsubr.h>
+# include <sys/strsun.h>
+#endif
+#ifdef __hpux
+# include <sys/dlpi_ext.h>
+# include <net/mtcp.h>
+#endif
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <net/if.h>
+#include <netinet/if_ether.h>
+#ifdef sun
+# include <inet/common.h>
+# if SOLARIS2 >= 8
+#  include <netinet/ip6.h>
+# else
+#  include <net/if_dl.h>
+# endif
+# if SOLARIS2 >= 10
+#  include <sys/policy.h>
+# endif
+# undef IPOPT_EOL
+# undef IPOPT_NOP
+# undef IPOPT_LSRR
+# undef IPOPT_SSRR
+# undef IPOPT_RR
+# include <inet/ip.h>
+# include <inet/ip_if.h>
+#endif
+
+#include "compat.h"
+#include "qif.h"
+#include "pfil.h"
+#include "pfild.h"
+
+#if SOLARIS2 >= 10
+extern queue_t *pfildq;
+#endif
+
+#undef	IEEESAP_SNAP
+#define	IEEESAP_SNAP		0xAA	/* SNAP SAP */
+
+#ifdef	PFILDEBUG
+# define	PRINT(l,x)	do {if ((l) <= pfildebug) cmn_err x; } while (0)
+# define	QTONM(x)	(((x) && (x)->q_ptr) ? \
+				 ((qif_t *)(x)->q_ptr)->qf_name : "??")
+#else
+# define	PRINT(l,x)	;
+#endif
+
+#ifndef	IP_DL_SAP
+# define	IP_DL_SAP	0x800
+#endif
+
+#define	AFtoSAP(af)	(((af) == AF_INET6) ? IP6_DL_SAP : IP_DL_SAP)
+
+static	int	pfil_drv_priv __P((cred_t *));
+
+
+#ifdef  PFILDEBUG
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_printmchain                                            */
+/* Returns:     void                                                        */
+/* Parameters:  mp(I) - pointer to mblk message                             */
+/*                                                                          */
+/* This is primarly for debugging purposes - print out the contents of a    */
+/* STREAMS mblk message, just by data block type or also contents (in hex)  */
+/* if the value of pfil_debug has been turned up enough.                    */
+/* ------------------------------------------------------------------------ */
+void pfil_printmchain(mblk_t *mp)
+{
+	char buf[80], cbuf[17], *t;
+	u_char c, *s, *r;
+	mblk_t *mc;
+	int i;
+
+	for (mc = mp; mc; mc = mc->b_cont) {
+		i = mc->b_wptr - mc->b_rptr;
+		/*LINTED: E_CONSTANT_CONDITION*/
+		PRINT(50,(CE_CONT, "m(%p):%d len %d cont %p\n",
+			(void *)mc, MTYPE(mc), i, (void *)mc->b_cont));
+		s = (u_char *)mc->b_rptr;
+		r = (u_char *)cbuf;
+		for (i = 0, t = buf; s < mc->b_wptr; ) {
+			c = *s++;
+			if (c >= 0x20  && c < 0x7f)
+				*r++ = c;
+			else
+				*r++ = '.';
+			*r = '\0';
+#ifdef	__hpux
+			sprintf(t, 4, "%02x", c);
+#else
+			(void)sprintf(t, "%02x", c);
+#endif
+			t += 2;
+			i++;
+			if ((i & 15) == 0) {
+				/*LINTED: E_CONSTANT_CONDITION*/
+				PRINT(99,(CE_CONT, "%03d:%s %s\n", i - 16,
+					buf, cbuf));
+				t = buf;
+				r = (u_char *)cbuf;
+			} else if ((i & 3) == 0)
+				*t++ = ' ';
+		}
+		if (t > buf) {
+			/*LINTED: E_CONSTANT_CONDITION*/
+			PRINT(99,(CE_CONT, "%03d:%s %s\n", i - (i & 15), buf,
+				cbuf));
+		}
+	}
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_printioctl                                             */
+/* Returns:     void                                                        */
+/* Parameters:  mp(I) - pointer to mblk message with ioctl                  */
+/*                                                                          */
+/* This is primarly for debugging purposes - print out in a more legible    */
+/* format what an ioctl is.                                                 */
+/* ------------------------------------------------------------------------ */
+static void pfil_printioctl(mblk_t *mp)
+{
+	struct iocblk *iocp;
+	int cmd, num;
+	char buf[80], l;
+
+	if (!mp || !mp->b_datap || !mp->b_datap->db_base)
+		return;
+	iocp = (struct iocblk *)mp->b_rptr;
+	cmd = iocp->ioc_cmd;
+
+#ifdef __hpux
+	sprintf(buf, sizeof(buf), "0x%x=_IO", cmd);
+#else
+	(void)sprintf(buf, "0x%x=_IO", cmd);
+#endif
+	switch (cmd >> 24)
+	{
+	case 0x20:
+		(void)strcat(buf, "V(");
+		break;
+	case 0x40:
+		(void)strcat(buf, "R(");
+		break;
+	case 0x80:
+		(void)strcat(buf, "W(");
+		break;
+	case 0xc0:
+		(void)strcat(buf, "WR(");
+		break;
+	default :
+#ifdef __hpux
+		sprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+			"0x%x(", cmd >> 24);
+#else
+		(void)sprintf(buf + strlen(buf), "0x%x(", cmd >> 24);
+#endif
+		break;
+	}
+
+	cmd &= 0x00ffffff;
+	num = cmd & 0xff;
+	l = (cmd >> 8) & 0xff;
+#ifdef	__hpux
+	sprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+		"%c,%d,%d)", l, num, (cmd >> 16) & 0xff);
+#else
+	(void)sprintf(buf + strlen(buf), "%c,%d,%d)",
+		l, num, (cmd >> 16) & 0xff);
+#endif
+	/*LINTED: E_CONSTANT_CONDITION*/
+	PRINT(3,(CE_CONT,
+		 "!pfil_printioctl: %s (%d) cr %p id %d flag 0x%x count %ld error %d rval %d\n",
+		 buf, (int)sizeof(*iocp), (void *)iocp->ioc_cr, iocp->ioc_id,
+		 iocp->ioc_flag, iocp->ioc_count, iocp->ioc_error,
+		 iocp->ioc_rval));
+	pfil_printmchain(mp);
+}
+#endif	/* PFILDEBUG */
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfilbind                                                    */
+/* Returns:     int  - 0 == success, else error                             */
+/* Parameters:  q(I) - pointer to queue                                     */
+/*                                                                          */
+/* Check to see if a queue (or the otherside of it) is missing a qif_t      */
+/* structure.  If neither have one then allocate a new one, else copy the   */
+/* q_ptr from one to the other.                                             */
+/* ------------------------------------------------------------------------ */
+int pfilbind(queue_t *q)
+{
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(3,(CE_CONT, "!pfilbind(%p) ptr %p O %p\n",
+		 (void *)q, (void *)q->q_ptr, (void *)OTHERQ(q)));
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(3,(CE_CONT, "!R %p %p W %p %p\n",
+		 (void *)RD(q), (void *)RD(q)->q_ptr,
+		 (void *)WR(q), (void *)WR(q)->q_ptr));
+
+	return qif_attach(q);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfilwput_ioctl                                              */
+/* Returns:     void                                                        */
+/* Parameters:  q(I)  - pointer to queue                                    */
+/*              mp(I) - pointer to STREAMS message                          */
+/*                                                                          */
+/* Handles ioctls for both the STREAMS module and driver.                   */
+/* ------------------------------------------------------------------------ */
+void pfilwput_ioctl(queue_t *q, mblk_t *mp)
+{
+	struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
+	qif_t *qif;
+
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(3,(CE_CONT,
+		 "!pfilwput_ioctl(%p,%p) ioctl(%x,%d,%x,%ld,%d,%d) [%s]\n",
+		 (void *)q, (void *)mp, iocp->ioc_cmd, iocp->ioc_id,
+		 iocp->ioc_flag, iocp->ioc_count, iocp->ioc_rval,
+		 iocp->ioc_error, QTONM(q)));
+#ifdef	PFILDEBUG
+	pfil_printioctl(mp);
+#endif
+
+	if (iocp->ioc_cr && pfil_drv_priv(iocp->ioc_cr) != 0 ) {
+		putnext(q, mp);
+		return;
+	}
+
+	switch (iocp->ioc_cmd)
+	{
+	case DL_IOC_HDR_INFO :
+		qif = q->q_ptr;
+
+		/*
+		 * Fastpath information ioctl.  Update the expected size for
+		 * headers on this queue using to match that in this message.
+		 * Whilst this may not be an IOCACK with the header attached,
+		 * it can also be an indication that something has changed so
+		 * doing an update may not be a bad idea.
+		 * If fastpath headers ever have variable length, this will
+		 * not work.
+		 */
+		WRITE_ENTER(&pfil_rw);
+		qif_update(qif, mp);
+		RW_EXIT(&pfil_rw);
+		if (qif->qf_ill != NULL) {
+			packet_filter_hook_t *pfh;
+
+			READ_ENTER(&pfh_sync.ph_lock);
+			pfh = pfil_hook_get(PFIL_IN, &pfh_sync);
+			for (; pfh; pfh = pfh->pfil_next)
+				if (pfh->pfil_func)
+					(void) (*pfh->pfil_func)(NULL, 0,
+								 qif->qf_ill,
+								 0, qif, NULL);
+			RW_EXIT(&pfh_sync.ph_lock);
+		}
+		break;
+
+#if SOLARIS2 >= 10
+#ifdef SIOCSLIFNAME
+	case SIOCSLIFNAME :
+		if (miocpullup(mp, sizeof(struct lifreq)) == 0) {
+			struct lifreq *lifr;
+			int sap;
+
+			lifr = (struct lifreq *)mp->b_cont->b_rptr;
+# ifdef ILLF_IPV6
+			sap = (lifr->lifr_flags & ILLF_IPV6) ? IP6_DL_SAP :
+							       IP_DL_SAP;
+# else
+			sap = IP_DL_SAP;
+# endif
+			pfil_addif(RD(q), lifr->lifr_name, sap);
+			miocack(q, mp, 0, 0);
+			return;
+		}
+		break;
+#endif
+#else /* pre-S10 */
+#ifdef	SIOCGTUNPARAM
+	case SIOCGTUNPARAM :
+		qif_attach(q);
+		break;
+#endif
+#endif /* pre-S10 */
+#ifdef __hpux
+	case ND_SET :
+	case ND_GET :
+		if (pfil_ioctl_nd(q, mp)) {
+			if (iocp->ioc_error)
+				iocp->ioc_count = 0;
+			mp->b_datap->db_type = M_IOCACK;
+			qreply(q, mp);
+		} else {
+			miocnak(q, mp, 0, EINVAL);
+		}
+		return;
+		break;
+#endif
+	default :
+		break;
+	}
+
+	putnext(q, mp);
+	return;
+}
+
+
+#if SOLARIS2 >= 10
+/*
+ * Update interface configuration data from pfild message.
+ */
+static void 
+pfil_update_ifaddrs(mblk_t *mp)
+{
+	s_ill_t *ill;
+	int i;
+	struct pfil_ifaddrs *ifaddrslist = (struct pfil_ifaddrs *)mp->b_rptr;
+	int numifs;
+
+	if (MLEN(mp) < sizeof(struct pfil_ifaddrs))
+		return;
+
+	numifs = MLEN(mp) / sizeof (struct pfil_ifaddrs);
+	mutex_enter(&s_ill_g_head_lock);
+
+	for (i = 0; i < numifs; i++) {
+		int sap = AFtoSAP(ifaddrslist[i].localaddr.in.sin_family);
+
+		/* LINTED: E_CONSTANT_CONDITION */
+		PRINT(3,(CE_CONT,"ifs# %d sin_family %d sap %x\n", i,
+			 ifaddrslist[i].localaddr.in.sin_family, sap)); 
+
+		for (ill = s_ill_g_head; ill; ill = ill->ill_next) {
+			if (strncmp(ifaddrslist[i].name, ill->ill_name,
+				    LIFNAMSIZ) == 0 &&
+			    sap == ill->ill_sap) {
+				bcopy(&ifaddrslist[i].localaddr,
+				      &ill->localaddr,
+				      sizeof (ifaddrslist[i].localaddr));
+				bcopy(&ifaddrslist[i].netmask, &ill->netmask,
+				      sizeof (ifaddrslist[i].netmask));
+				bcopy(&ifaddrslist[i].broadaddr,
+				      &ill->broadaddr,
+				      sizeof (ifaddrslist[i].broadaddr));
+				bcopy(&ifaddrslist[i].dstaddr, &ill->dstaddr,
+				      sizeof (ifaddrslist[i].dstaddr));
+				ill->mtu = ifaddrslist[i].mtu;
+			}
+		}
+	}
+
+	mutex_exit(&s_ill_g_head_lock);
+}
+
+
+/*
+ * Update valid address set data from pfild message.
+ */
+static void pfil_update_ifaddrset(mblk_t *mp)
+{
+	struct pfil_ifaddrset *ifaddrset = (struct pfil_ifaddrset *)mp->b_rptr;
+	int sap;
+	qif_t *qp;
+
+	if (MLEN(mp) < sizeof(struct pfil_ifaddrset))
+		return;
+
+	sap = AFtoSAP(ifaddrset->af);
+
+	READ_ENTER(&pfil_rw);
+
+	qp = qif_iflookup(ifaddrset->name, sap);
+	if (qp != NULL) {
+		if (qp->qf_addrset != NULL)
+			freeb(qp->qf_addrset);
+		qp->qf_addrset = dupb(mp);
+	}
+
+	RW_EXIT(&pfil_rw);
+}
+#endif /* SOLARIS2 >= 10 */
+
+
+/************************************************************************
+ * STREAMS device functions
+ */
+/* ------------------------------------------------------------------------ */
+/* Function:    pfilwput                                                    */
+/* Returns:     void                                                        */
+/* Parameters:  q(I)  - pointer to queue                                    */
+/*              mp(I) - pointer to STREAMS message                          */
+/*                                                                          */
+/* This is only called for interaction with pfil itself, as the driver      */
+/* /dev/pfil, not the STREAMS module pushed on another queue.  As it does   */
+/* not do any IO, this should never be called except to handle ioctl's and  */
+/* so all other messages are free'd and no reply sent back.                 */
+/* The only ioctls handled by the driver are ND_GET/ND_SET.                 */
+/* pfilwput also handles PFILCMD_IFADDRS and PFILCMD_IFADDRSET messages.    */
+/* NOTE: HP-UX does not need or have pfil implemented as a STREAMS device.  */
+/* ------------------------------------------------------------------------ */
+#ifdef sun
+void pfilwput(queue_t *q, mblk_t *mp)
+{
+	struct iocblk *iocp;
+	uint32_t cmd;
+
+# ifdef PFILDEBUG
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(9,(CE_CONT, "!pfilwput(%p,%p) [%s] qif %p\n",
+		 (void *)q, (void *)mp, QTONM(q), (void *)q->q_ptr));
+# endif
+
+	switch (MTYPE(mp))
+	{
+#if SOLARIS2 >= 10
+	case M_PROTO:
+		/*
+		 * Is it a valid PFILCMD message?
+		 */
+		if (MLEN(mp) < sizeof(uint32_t) || (mp->b_cont == NULL)) {
+			/*LINTED: E_CONSTANT_CONDITION*/
+			PRINT(10, (CE_NOTE, "invalid PFILCMD"));
+			break;
+		}
+
+		/*
+		 * It's a message from pfild.  Remember pfild's read queue for
+		 * later use when sending packets; then process this message.
+		 */
+		pfildq = RD(q);
+		cmd = *((uint32_t *)mp->b_rptr);
+		switch (cmd) {
+		case PFILCMD_IFADDRS:
+			pfil_update_ifaddrs(mp->b_cont);
+			break;
+		case PFILCMD_IFADDRSET:
+			pfil_update_ifaddrset(mp->b_cont);
+			break;
+		default:
+			break;
+		}
+		break;
+#endif
+	case M_IOCTL:
+		iocp = (struct iocblk *)mp->b_rptr;
+		switch (iocp->ioc_cmd)
+		{
+		case ND_SET :
+		case ND_GET :
+			if (pfil_ioctl_nd(q, mp)) {
+				if (iocp->ioc_error)
+					iocp->ioc_count = 0;
+				mp->b_datap->db_type = M_IOCACK;
+				qreply(q, mp);
+			} else {
+				miocnak(q, mp, 0, EINVAL);
+			}
+			break;
+
+		default :
+			miocnak(q, mp, 0, EINVAL);
+			break;
+		}
+		return;
+
+	default :
+		break;
+	}
+
+	freemsg(mp);
+}
+#endif
+
+
+/************************************************************************
+ * STREAMS module functions
+ */
+/* ------------------------------------------------------------------------ */
+/* Function:    pfilmodwput                                                 */
+/* Returns:     void                                                        */
+/* Parameters:  q(I)  - pointer to queue                                    */
+/*              mp(I) - pointer to STREAMS message                          */
+/*                                                                          */
+/* This function is called as part of the STREAMS module message processing */
+/* for messages going down to the device drivers.                           */
+/* ------------------------------------------------------------------------ */
+void pfilmodwput(queue_t *q, mblk_t *mp)
+{
+	union DL_primitives *dl;
+	qif_t *qif;
+
+	qif = q->q_ptr;
+
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(9,(CE_CONT, "!pfilmodwput(%p,%p) T:%d [%s,%s] qif %p %p\n",
+		 (void *)q, (void *)mp, MTYPE(mp), QTONM(q), QTONM(OTHERQ(q)),
+		 (void *)qif, (void *)qif->qf_ill));
+
+	switch (MTYPE(mp))
+	{
+	case M_PROTO :
+	case M_PCPROTO :
+		dl = (union DL_primitives *)mp->b_rptr;
+
+		/* LINTED: E_CONSTANT_CONDITION */
+		PRINT(7,(CE_CONT, "!pfilmodwput: %p dl_primitive:%d\n",
+			 (void *)mp, dl->dl_primitive));
+
+		if ((MLEN(mp) < sizeof(dl_unitdata_req_t)) ||
+		    (dl->dl_primitive != DL_UNITDATA_REQ)) {
+			break;
+		}
+
+		/*FALLTHROUGH*/
+	case M_DATA :
+		atomic_add_long(&qif->qf_nw, 1);
+
+		if (qif->qf_ill != NULL) {
+			int i;
+
+			i = pfil_precheck(q, &mp, PFIL_OUT, qif);
+
+			/* LINTED: E_CONSTANT_CONDITION */
+			PRINT(9, (CE_CONT, "!%s: pfil_precheck=%d mp %p\n",
+				  "pfilmodwput", i, (void *)mp));
+			if (mp == NULL)
+				return;
+			else if (i > 0) {
+				freemsg(mp);
+				return;
+			}
+		}
+		break;
+
+	case M_IOCTL :
+		pfilwput_ioctl(q, mp);
+		return;
+
+	default :
+		break;
+	}
+
+	putnext(q, mp);
+	return;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfilmodrput                                                 */
+/* Returns:     void                                                        */
+/* Parameters:  q(I)  - pointer to queue                                    */
+/*              mp(I) - pointer to STREAMS message                          */
+/*                                                                          */
+/* This function is called as part of the STREAMS module message processing */
+/* for messages going up to the protocol stack.                             */
+/* ------------------------------------------------------------------------ */
+void pfilmodrput(queue_t *q, mblk_t *mp)
+{
+	union DL_primitives *dl;
+	dl_bind_ack_t *b;
+	int i, flags;
+	qif_t *qif;
+
+	flags = 0;
+	qif = q->q_ptr;
+
+	/* LINTED: E_CONSTANT_CONDITION */
+	PRINT(9,(CE_CONT, "!pfilmodrput(%p,%p) T:%d [%s,%s] qif %p %p\n",
+		 (void *)q, (void *)mp, mp->b_datap->db_type, QTONM(q),
+		 QTONM(OTHERQ(q)), (void *)qif,
+		 (void *)qif->qf_ill));
+
+	switch (MTYPE(mp))
+	{
+#ifdef	DL_IOC_HDR_INFO
+	case M_IOCACK :
+	{
+		struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
+
+		if (iocp->ioc_cmd == DL_IOC_HDR_INFO) {
+			WRITE_ENTER(&pfil_rw);
+			qif_update(qif, mp);
+			RW_EXIT(&pfil_rw);
+		}
+		/*FALLTHROUGH*/
+	}
+#endif	/* DL_IOC_HDR_INFO */
+#ifdef	PFILDEBUG
+	case M_IOCNAK :
+	case M_IOCTL :
+		pfil_printioctl(mp);
+#endif
+		break;
+
+	case M_PROTO :
+	case M_PCPROTO :
+
+		dl = (union DL_primitives *)mp->b_rptr;
+
+		/* LINTED: E_CONSTANT_CONDITION */
+		PRINT(7,(CE_CONT, "!mp:%p pfilmodrput:dl_primitive:%d\n",
+			 (void *)mp, dl->dl_primitive));
+
+		switch (dl->dl_primitive)
+		{
+		case DL_UNITDATA_IND :
+			if ((MLEN(mp) >= sizeof(dl_unitdata_ind_t)) &&
+			    (dl->unitdata_ind.dl_group_address))
+				flags |= PFIL_GROUP;
+			break;
+
+		case DL_SUBS_BIND_ACK :
+			if (qif->qf_waitack > 0) { 
+				dl_subs_bind_ack_t *c;
+
+				c = (dl_subs_bind_ack_t *)dl;
+				if (qif->qf_sap == 0) {
+#if 0
+					qif->qf_sap = c->dl_sap;
+					if (qif->qf_sap < 0)
+						qif->qf_sap = -qif->qf_sap;
+#else
+					cmn_err(CE_NOTE, "c:off %u len %u",
+						c->dl_subs_sap_offset,
+						c->dl_subs_sap_length);
+#endif
+				}
+
+				(void) pfilbind(q);
+				if (qif->qf_waitack > 0)
+					qif->qf_waitack--;
+			}
+			break;
+
+		case DL_BIND_ACK :
+			b = (dl_bind_ack_t *)dl;
+			if (qif->qf_sap == 0) {
+				qif->qf_sap = b->dl_sap;
+				if (qif->qf_sap < 0)
+					qif->qf_sap = -qif->qf_sap;
+			}
+
+			if (b->dl_sap == IEEESAP_SNAP) {
+				qif->qf_waitack++;
+				break;
+			}
+
+			if (!b->dl_sap || b->dl_sap == IP_DL_SAP ||
+			    b->dl_sap == IP6_DL_SAP)
+				(void) pfilbind(q);
+			break;
+
+		default :
+			break;
+		}
+
+		if ((MLEN(mp) < sizeof(dl_unitdata_ind_t)) ||
+		    (dl->dl_primitive != DL_UNITDATA_IND))
+			break;
+
+		/*FALLTHROUGH*/
+	case M_DATA :
+		atomic_add_long(&qif->qf_nr, 1);
+
+		if (qif->qf_ill != NULL) {
+			flags |= PFIL_IN;
+			i = pfil_precheck(q, &mp, flags, qif);
+
+			/* LINTED: E_CONSTANT_CONDITION */
+			PRINT(9, (CE_CONT,
+				  "!pfilmodrput: mp %p pfil_precheck=%d\n",
+				  (void *)mp, i));
+			if (mp == NULL)
+				return;
+			else if (i > 0) {
+				freemsg(mp);
+				return;
+			}
+		}
+		break;
+
+	default :
+		break;
+	}
+
+	putnext(q, mp);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_drv_priv                                               */
+/* Returns:     int   - 0 == success, EPERM for error.                      */
+/* Parameters:  cr(I) - pointer to credential information                   */
+/*                                                                          */
+/* Checks to see if the caller has enough credentials.                      */
+/* ------------------------------------------------------------------------ */
+static int pfil_drv_priv(cred_t *cr)
+{
+#if SOLARIS2 >= 10
+	return (secpolicy_net_config(cr, B_TRUE));
+#else
+# ifdef sun
+	return (suser(cr) ? 0 : EPERM);
+# else
+	return (suser() ? 0 : EPERM);
+# endif
+#endif
+}
+
+
+/************************************************************************
+ * kernel module initialization
+ */
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_startup                                                */
+/* Returns:     void                                                        */
+/* Parameters:  None.                                                       */
+/*                                                                          */
+/* Initialise pfil data strutures.                                          */
+/* ------------------------------------------------------------------------ */
+void pfil_startup()
+{
+	pfil_init(&pfh_inet4);
+	pfil_init(&pfh_inet6);
+	pfil_init(&pfh_sync);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/uts/common/inet/pfil/pkt.c	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2000, 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef __hpux
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+#endif
+
+#include <sys/types.h>
+#include <sys/stream.h>
+#include <sys/cmn_err.h>
+#include <sys/ddi.h>
+#include <sys/rwlock.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#if SOLARIS2 >= 8
+# include <netinet/ip6.h>
+#else
+# include <net/if_dl.h>
+#endif
+
+#undef IPOPT_EOL
+#undef IPOPT_NOP
+#undef IPOPT_RR
+#undef IPOPT_LSRR
+#undef IPOPT_SSRR
+#include <inet/common.h>
+#include <inet/ip.h>
+#if SOLARIS2 >= 8
+#include <inet/ip6.h>
+#endif
+#include <inet/ip_ire.h>
+#include <inet/ip_if.h>
+
+#include "compat.h"
+#include "qif.h"
+
+
+extern krwlock_t pfil_rw;
+extern queue_t *pfildq;
+
+#if 1
+/* ------------------------------------------------------------------------ */
+/* Function: pfil_make_dl_packet (mb, ip, dst, ifname, output_q)            */
+/* Returns: On success, datalink msg block.                                 */
+/*	    On failure, NULL.                                               */
+/* Parameters:								    */
+/*	mblk_t *mb: IP message block       				    */
+/*      struct ip *ip: ip header start pointer				    */
+/*      void *dst: destination address.                                     */
+/*            if it is null, destination address is in ip                   */
+/*            for IPV4, the parameter should be an instance of in_addr      */
+/*            for IPV6, the parameter should be an instance of in6_addr     */
+/*      char *ifname: output interface name                                 */
+/*            if neither of dst and ifname is NULL, the routing for dst     */
+/*            should have same interface name as ifname;                    */
+/*            If ifname is NULL,  output interface name is not specified    */
+/*            so it is decided by routing table.                            */
+/*            if dst is NULL(ifname is not NULL), destination address       */
+/*            in IP packet will be used for routing lookup, and the packet  */
+/*            will be send out to interface ifname                          */
+/*      queue_t **output_q: the write queue of pfil module where the        */
+/*            returned message block can be putnext                         */ 
+/*                                                                          */
+/* This function is called to make a datalink message based on the IP       */
+/* message block mb, If the function successfully returns, output_q         */ 
+/* is set to the pfil module's write queue of output interface. Please use  */ 
+/* pfil_send_dl_packet to putnext the returned packet to output_q.          */
+/*                                                                          */
+/* This function will return with a 'lock' held on the qif structure via    */
+/* the PT_ENTER_READ() macro if qif_iflookup succeeds.  This lock is then   */
+/* intended to be released when the queue returned is no longer referenced. */
+/*                                                                          */
+/* fr_fastroute, fr_send_icmp_err, fr_send_reset will call this func to     */
+/* prepare packet.                                                          */
+/*                                                                          */
+/* ip_nexthop[_route] is called to search routing info in this func.        */
+/* ------------------------------------------------------------------------ */
+mblk_t *pfil_make_dl_packet(mb, ip, dst, ifname, output_q)
+mblk_t *mb;
+struct ip *ip;
+void *dst;
+char *ifname;
+queue_t **output_q;
+{
+	mblk_t *mp;
+	qif_t *qif;
+	int ip_inf_bind = 0;
+	char out_ifname_buf[LIFNAMSIZ];
+	struct sockaddr_storage target;
+	int sap;
+
+	if (ip->ip_v == IPV4_VERSION) {
+		struct sockaddr_in *target_in;
+		target_in = (struct sockaddr_in *)&target;
+		sap = IP_DL_SAP;
+		target_in->sin_family = AF_INET;
+		if (dst == NULL)
+			target_in->sin_addr = ip->ip_dst;
+		else {
+			target_in->sin_addr.s_addr = *(ipaddr_t *)dst;
+			if (ifname != NULL)
+				ip_inf_bind = 1;
+		}
+	}
+#ifdef USE_INET6
+	else if (ip->ip_v == IPV6_VERSION) {
+		struct sockaddr_in6 *target_in6;
+		target_in6 = (struct sockaddr_in6 *)&target;
+		sap = IP6_DL_SAP;
+		target_in6->sin6_family = AF_INET6;
+		if (dst == NULL)
+			target_in6->sin6_addr = ((ip6_t *)ip)->ip6_dst;
+		else {
+			bcopy(dst, &target_in6->sin6_addr,
+			      sizeof(struct in6_addr));
+			if (ifname != NULL)
+				ip_inf_bind = 1;
+		}
+	}
+#endif
+
+	if (ip_inf_bind)
+		mp = ip_nexthop((struct sockaddr *)&target, ifname);
+	else {
+		mp = ip_nexthop_route((struct sockaddr *)&target,
+				      out_ifname_buf);
+		if (ifname == NULL)
+			ifname = out_ifname_buf;
+	}
+
+	if (mp == NULL)
+		return NULL;
+
+	/*
+	 * Sometimes the ip_nexthop* functions can't give us a usable packet
+	 * header, for example, when the (nexthop) destination is in need of
+	 * address resolution.  We'd like to punt our packet up to pfild and
+	 * let it send the packet through the normal IP mechanisms, which will
+	 * handle ARP/ND, but if the packet is being sent to an explicit router
+	 * there is no way pfild can indicate that to the IP stack.  So in
+	 * desperation, we discard the packet we are working on and instead
+	 * construct an IP packet with ip_p == 0 to the nexthop router and let
+	 * pfild send that.  This will start the ARP/ND resolution process
+	 * so that next time we need to send a packet to that router, the IRE
+	 * cache is all ready to go.
+	 */
+	if ((MTYPE(mp) == M_PROTO) && (dst != NULL))
+		if ((ip->ip_v == IPV4_VERSION) &&
+		    (ip->ip_dst.s_addr != *(ipaddr_t *)dst)) {
+
+			ASSERT(MTYPE(mb) == M_DATA);
+			if (mb->b_cont != NULL) {
+				freemsg(mb->b_cont);
+				mb->b_cont = NULL;
+			}
+
+			/*
+			 * We don't bother to calculate the IP checksum, raw
+			 * socket will finally do it.
+			 */
+			ip = (struct ip *)mb->b_rptr;
+			ip->ip_hl = 5;
+			ip->ip_tos = 0;
+			ip->ip_len = sizeof (struct ip);
+			ip->ip_id = 0;
+			ip->ip_off = 0;
+			ip->ip_ttl = 1;
+			ip->ip_p = 0;
+			ip->ip_src = *(struct in_addr *)dst;
+			ip->ip_dst = *(struct in_addr *)dst;
+
+			mb->b_wptr = mb->b_rptr + sizeof (struct ip);
+		}
+
+	/* look for output queue */
+	rw_enter(&pfil_rw, RW_READER);
+	qif = (qif_t *)qif_iflookup(ifname, sap);
+	if (qif == NULL) {
+		rw_exit(&pfil_rw);
+		freeb(mp);
+		return NULL;
+	}
+
+	PT_ENTER_READ(&qif->qf_ptl);
+	*output_q = WR(qif->qf_q);
+	rw_exit(&pfil_rw);
+
+	/* OK, by now, we can link the IP message to lay2 header */
+	linkb(mp, mb);
+	mb = mp;
+
+	return mb;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: pfil_send_dl_packet (output_q, mb)                             */
+/* Returns: void                                                            */
+/* Parameters:								    */
+/*      queue_t *output_q: pfil module's write queue                        */
+/*	mblk_t *mb: Lay2 message block. This parameter should be the return */
+/*                  value of pfil_make_layer2_packet             	    */
+/* This function is called to send the packet returned by                   */
+/* pfil_make_dl_packet.                                                     */
+/* In this function, PT_EXIT_READ is used after the putnext call to release */
+/* the qif structure held by function pfil_make_layer2_packet.              */
+/* ------------------------------------------------------------------------ */
+void pfil_send_dl_packet(output_q, mb)
+queue_t *output_q;
+mblk_t *mb;
+{
+	qif_t *qif;
+
+	/*
+	 * NOTE: It is not permitted to hold a lock across putnext() so we
+	 * use a semaphore-like operation to signal when it is ok to delete
+	 * the qif structure.  With the current locking structure, putnext()
+	 * may be called here after qprocsoff() has been called on output_q,
+	 * but before the queue was completely closed.  See pfilmodclose().
+	 */
+
+	if (MTYPE(mb) == M_PROTO && pfildq != NULL) {
+		/*
+		 * If pfil_make_dl_packet() returned an M_PROTO message it's
+		 * probably an ARP AR_ENTRY_QUERY message, which we can't
+		 * handle, so we just send the IP packet up to pfild to
+		 * transmit it via a raw socket.
+		 */
+		putnext(pfildq, mb->b_cont);
+		mb->b_cont = NULL;
+		freemsg(mb);
+	} else {
+		putnext(output_q, mb);
+	}
+
+	qif = output_q->q_ptr;
+	PT_EXIT_READ(&qif->qf_ptl);
+}
+
+#else /* pfil_sendbuf implementation for no IRE_ILL_CN definition */
+
+/* ------------------------------------------------------------------------ */
+/* Function:    pfil_sendbuf                                                */
+/* Returns:     int  - 0 == success, 1 == failure                           */
+/* Parameters:  m(I) - pointer to streams message                           */
+/*                                                                          */
+/* Output an IPv4 packet to whichever interface has the correct route.      */
+/* ------------------------------------------------------------------------ */
+int pfil_sendbuf(m)
+mblk_t *m;
+{
+	queue_t *q = NULL;
+	struct ip *ip;
+	size_t hlen;
+	ire_t *dir;
+	u_char *s;
+	ill_t *il;
+
+	ip = (struct ip *)m->b_rptr;
+
+#ifdef	MATCH_IRE_DSTONLY
+	dir = ire_route_lookup(ip->ip_dst.s_addr, 0xffffffff, 0, 0,
+				NULL, NULL, NULL,
+				MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|
+				MATCH_IRE_RECURSIVE);
+#else
+	dir = ire_lookup(ip->ip_dst.s_addr);
+#endif
+
+	if (dir) {
+#if SOLARIS2 < 8
+		if (!dir->ire_ll_hdr_mp || !dir->ire_ll_hdr_length)
+#elif (SOLARIS2 >= 8) && (SOLARIS2 <= 10)
+		if (!dir->ire_fp_mp || !dir->ire_dlureq_mp)
+#else
+		if (dir->ire_nce && dir->ire_nce->nce_state != ND_REACHABLE)
+#endif
+			return 2;
+	}
+
+	if (dir) {
+		mblk_t *mp, *mp2;
+
+		il = ire_to_ill(dir);
+		if (!il)
+			return 2;
+#if SOLARIS2 < 8
+		mp = dir->ire_ll_hdr_mp;
+		hlen = dir->ire_ll_hdr_length;
+
+#elif ((SOLARIS2 >= 8) && (SOLARIS2 <= 10)
+		mp = dir->ire_fp_mp;
+		hlen = mp ? mp->b_wptr - mp->b_rptr : 0;
+		mp = dir->ire_dlureq_mp;
+#else
+		mp = dir->ire_nce->nce_fp_mp;
+		hlen = mp ? mp->b_wptr - mp->b_rptr : 0;
+		mp = dir->ire_nce->nce_res_mp;
+#endif
+		s = (u_char *)ip;
+
+		if (hlen &&
+#ifdef	ICK_M_CTL_MAGIC
+		    (il->ill_ick.ick_magic != ICK_M_CTL_MAGIC) &&
+#endif
+		    (s - m->b_datap->db_base) >= hlen) {
+			s -= hlen;
+			m->b_rptr = (u_char *)s;
+			bcopy((char *)mp->b_rptr, (char *)s, hlen);
+		} else {
+			mp2 = copyb(mp);
+			if (!mp2)
+				goto bad_nexthop;
+			mp2->b_cont = m;
+			m = mp2;
+		}
+
+		if (dir->ire_stq)
+			q = dir->ire_stq;
+		else if (dir->ire_rfq)
+			q = WR(dir->ire_rfq);
+		if (q)
+			q = q->q_next;
+		if (q) {
+			RW_EXIT(&pfil_rw);
+			putnext(q, m);
+			READ_ENTER(&pfil_rw);
+			return 0;
+		}
+	}
+bad_nexthop:
+	freemsg(m);
+	return 1;
+}
+#endif /* 1 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/uts/common/inet/pfil/qif.c	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,859 @@
+/*
+ * Copyright (C) 2000, 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/uio.h>
+#include <sys/buf.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/modctl.h>
+#include <sys/open.h>
+#include <sys/kmem.h>
+#include <sys/conf.h>
+#include <sys/cmn_err.h>
+#include <sys/stat.h>
+#include <sys/cred.h>
+#include <sys/dditypes.h>
+#include <sys/stream.h>
+#include <sys/poll.h>
+#include <sys/autoconf.h>
+#include <sys/byteorder.h>
+#include <sys/socket.h>
+#include <sys/dlpi.h>
+#include <sys/stropts.h>
+#include <sys/sockio.h>
+#include <sys/ethernet.h>
+#include <net/if.h>
+#if SOLARIS2 >= 6
+# include <net/if_types.h>
+# if SOLARIS2 >= 8
+#  include <netinet/ip6.h>
+# endif
+# include <net/if_dl.h>
+#endif
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <inet/common.h>
+#undef IPOPT_EOL
+#undef IPOPT_NOP
+#undef IPOPT_LSRR
+#undef IPOPT_SSRR
+#undef IPOPT_RR
+#include <inet/ip.h>
+#include <inet/ip_if.h>
+#include <inet/ip_ire.h>
+
+#include "compat.h"
+#include "qif.h"
+#include "pfil.h"
+
+
+#if SOLARIS2 >= 6
+static	size_t	hdrsizes[57][2] = {
+	{ 0, 0 },
+	{ IFT_OTHER, 0 },
+	{ IFT_1822, 0 },
+	{ IFT_HDH1822, 0 },
+	{ IFT_X25DDN, 0 },
+	{ IFT_X25, 0 },
+	{ IFT_ETHER, 14 },
+	{ IFT_ISO88023, 0 },
+	{ IFT_ISO88024, 0 },
+	{ IFT_ISO88025, 0 },
+	{ IFT_ISO88026, 0 },
+	{ IFT_STARLAN, 0 },
+	{ IFT_P10, 0 },
+	{ IFT_P80, 0 },
+	{ IFT_HY, 0 },
+	{ IFT_FDDI, 24 },
+	{ IFT_LAPB, 0 },
+	{ IFT_SDLC, 0 },
+	{ IFT_T1, 0 },
+	{ IFT_CEPT, 0 },
+	{ IFT_ISDNBASIC, 0 },
+	{ IFT_ISDNPRIMARY, 0 },
+	{ IFT_PTPSERIAL, 0 },
+	{ IFT_PPP, 0 },
+	{ IFT_LOOP, 0 },
+	{ IFT_EON, 0 },
+	{ IFT_XETHER, 0 },
+	{ IFT_NSIP, 0 },
+	{ IFT_SLIP, 0 },
+	{ IFT_ULTRA, 0 },
+	{ IFT_DS3, 0 },
+	{ IFT_SIP, 0 },
+	{ IFT_FRELAY, 0 },
+	{ IFT_RS232, 0 },
+	{ IFT_PARA, 0 },
+	{ IFT_ARCNET, 0 },
+	{ IFT_ARCNETPLUS, 0 },
+	{ IFT_ATM, 0 },
+	{ IFT_MIOX25, 0 },
+	{ IFT_SONET, 0 },
+	{ IFT_X25PLE, 0 },
+	{ IFT_ISO88022LLC, 0 },
+	{ IFT_LOCALTALK, 0 },
+	{ IFT_SMDSDXI, 0 },
+	{ IFT_FRELAYDCE, 0 },
+	{ IFT_V35, 0 },
+	{ IFT_HSSI, 0 },
+	{ IFT_HIPPI, 0 },
+	{ IFT_MODEM, 0 },
+	{ IFT_AAL5, 0 },
+	{ IFT_SONETPATH, 0 },
+	{ IFT_SONETVT, 0 },
+	{ IFT_SMDSICIP, 0 },
+	{ IFT_PROPVIRTUAL, 0 },
+	{ IFT_PROPMUX, 0 },
+};
+#endif /* SOLARIS2 >= 6 */
+
+
+#if SOLARIS2 <= 6
+# include <sys/kmem_impl.h>
+#endif
+#if SOLARIS2 >= 10
+extern krwlock_t ill_g_lock;
+#endif
+
+#define	SAPNAME(x)	((x)->qf_sap == 0x0800 ? "IPv4" : \
+			 (x)->qf_sap == 0x86dd ? "IPv6" : "??")
+
+static	int		qif_num = 0;
+static	kmem_cache_t	*qif_cache = NULL;
+
+qif_t	*qif_head;
+int	qif_verbose = 0;
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    qif_startup                                                 */
+/* Returns:     int - 0 == success, -1 == failure                           */
+/* Parameters:  None.                                                       */
+/*                                                                          */
+/* Perform any initialisation of data structures related to managing qif's  */
+/* that is deemed necessary.                                                */
+/* ------------------------------------------------------------------------ */
+int qif_startup()
+{
+
+	qif_head = NULL;
+	qif_cache = kmem_cache_create("qif_head_cache", sizeof(qif_t), 8,
+				      NULL, NULL, NULL, NULL, NULL, 0);
+	if (qif_cache == NULL) {
+		cmn_err(CE_NOTE, "qif_startup:kmem_cache_create failed");
+		return -1;
+	}
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    qif_stop                                                    */
+/* Returns:     void                                                        */
+/* Parameters:  None.                                                       */
+/*                                                                          */
+/* Deallocate all qif_t's allocated and clean up any other data structures  */
+/* required in order to 'shut down' this part of the pfil module.           */
+/* ------------------------------------------------------------------------ */
+void qif_stop()
+{
+	kmem_cache_destroy(qif_cache);
+	qif_cache = NULL;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    q_to_ill                                                    */
+/* Returns:     void * - NULL == failure, else pointer to ill               */
+/* Parameters:  rq(I) - pointer to STREAMS read queue                       */
+/* Locks:       pfil_rw                                                     */
+/*                                                                          */
+/* Given a pointer to a queue, try and find the ill which owns it.          */
+/* ------------------------------------------------------------------------ */
+void *q_to_ill(rq)
+queue_t *rq;
+{
+#ifndef	IRE_ILL_CN
+	ill_t *ill = NULL;
+	queue_t *qu, *wq;
+
+	wq = OTHERQ(rq);
+	if (rq) {
+#if SOLARIS2 >= 10
+		ill_walk_context_t ctx;
+
+		rw_enter(&ill_g_lock, RW_READER);
+		for (ill = ILL_START_WALK_ALL(&ctx); ill != NULL;
+		     ill = ill_next(&ctx, ill))
+#else
+		for (ill = ill_g_head; ill != NULL; ill = ill->ill_next)
+#endif
+		{
+			if (ill->ill_rq == NULL || ill->ill_wq == NULL)
+				continue;
+			if (ill->ill_rq == RD(rq)->q_next)
+				break;
+			for (qu = WR(ill->ill_rq); qu; qu = qu->q_next)
+				if ((qu->q_ptr == rq->q_ptr) || (qu == wq))
+					break;
+			if (qu != NULL)
+				break;
+			for (qu = ill->ill_rq; qu; qu = qu->q_next)
+				if (qu->q_ptr == rq->q_ptr)
+					break;
+			if (qu != NULL)
+				break;
+		}
+	}
+#if SOLARIS2 >= 10
+	rw_exit(&ill_g_lock);
+#endif
+	return ill;
+#else /* IRE_ILL_CN */
+	s_ill_t *ill = NULL;
+
+	if (!rq)
+		return 0;
+
+	ASSERT(rq->q_flag & QREADR);
+
+	mutex_enter(&s_ill_g_head_lock);
+	for (ill = s_ill_g_head; ill; ill = ill->ill_next)
+		if (ill->ill_rq == rq)
+			break;
+	mutex_exit(&s_ill_g_head_lock);
+
+	return ill;
+#endif
+}
+
+
+#ifndef	IRE_ILL_CN
+/* ------------------------------------------------------------------------ */
+/* Function:    qif_ire_walker                                              */
+/* Returns:     void                                                        */
+/* Parameters:  ire(I) - pointer to an ire_t                                */
+/*              arg(I) - pointer to a qif                                   */
+/*                                                                          */
+/* This function gets called by the ire-walking function for each ire in    */
+/* table.  We enumerate through the ire looking for cached fastpath headers */
+/* on a given NIC (the qif) so we can update qf_hl from its size.           */
+/* ------------------------------------------------------------------------ */
+void
+qif_ire_walker(ire, arg)
+	ire_t *ire;
+	void *arg;
+{
+	qif_t *qif = arg;
+
+	if ((ire->ire_type == IRE_CACHE) &&
+#if SOLARIS2 >= 6
+	    (ire->ire_ipif != NULL) &&
+	    (ire->ire_ipif->ipif_ill == qif->qf_ill)
+#else
+	    (ire_to_ill(ire) == qif->qf_ill)
+#endif
+	    ) {
+#if SOLARIS2 < 8
+		mblk_t *m = ire->ire_ll_hdr_mp;
+#elif (SOLARIS2 >= 8) && (SOLARIS2 <= 10)
+		mblk_t *m = ire->ire_fp_mp;
+#else
+		mblk_t *m = ire->ire_nce->nce_fp_mp;
+#endif
+		if (m != NULL)
+			qif->qf_hl = m->b_wptr - m->b_rptr;
+	}
+}
+#endif
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    qif_attach                                                  */
+/* Returns:     int  - 0 == success, -1 == error in attaching qif_t to q    */
+/* Parameters:  rq(I) - pointer to STREAMS read queue                       */
+/* Write Lock:  pfil_rw                                                     */
+/*                                                                          */
+/* Attempt to bind a qif_t structure to a specific interface given the      */
+/* queue pointer.  Assumes the queue already has a qif_t structure tagged   */
+/* against it.                                                              */
+/* ------------------------------------------------------------------------ */
+int
+qif_attach(rq)
+	queue_t *rq;
+{
+	packet_filter_hook_t *pfh;
+	qif_t *qif;
+#ifdef IRE_ILL_CN
+	s_ill_t *ill;
+#else
+	ill_t *ill;
+#endif
+
+	WRITE_ENTER(&pfil_rw);
+	/*
+	 * Can we map the queue to a specific ill?  If not, go no futher, we
+	 * are only interested in being associated with queues that we can
+	 * recognise as being used for IP communication of some sort.
+	 */
+	ill = q_to_ill(rq);
+	if (ill == NULL) {
+		if (qif_verbose > 0)
+			cmn_err(CE_NOTE,
+				"PFIL: cannot find interface for rq %p",
+				(void *)rq);
+		RW_EXIT(&pfil_rw);
+		return -1;
+	}
+
+	qif = rq->q_ptr;
+#ifndef IRE_ILL_CN
+#if SOLARIS2 < 8
+	qif->qf_hl = ill->ill_hdr_length;
+#else
+	if ((ill->ill_type > 0) && (ill->ill_type < 0x37) &&
+	    (hdrsizes[ill->ill_type][0] == ill->ill_type))
+		qif->qf_hl = hdrsizes[ill->ill_type][1];
+
+	if (qif->qf_hl == 0 && ill->ill_type != IFT_OTHER) {
+		cmn_err(CE_WARN,
+			"!Unknown layer 2 header size for %s type %d sap %x\n",
+			qif->qf_name, ill->ill_type, ill->ill_sap);
+	}
+#endif
+#endif /* IRE_ILL_CN */
+
+	/*
+	 * Protect against the qif_t being bound against an interface, twice
+	 * by getting a lock on setting qf_bound and don't release it until
+	 * all the information has been set with qf_bound finally set to 1
+	 * after that.
+	 */
+	if (qif->qf_bound == 1) {
+		RW_EXIT(&pfil_rw);
+		return 0;
+	}
+
+	qif->qf_sap = ill->ill_sap;
+#ifndef IRE_ILL_CN
+	qif->qf_ppa = ill->ill_ppa;
+#endif
+#ifdef icmp_nextmtu
+	qif->qf_max_frag = ill->ill_max_frag;
+#endif
+	(void) strncpy(qif->qf_name, ill->ill_name, sizeof(qif->qf_name));
+	qif->qf_name[sizeof(qif->qf_name) - 1] = '\0';
+	qif->qf_ill = ill;
+	qif->qf_bound = 1;
+	qif_ipmp_syncslave(qif, qif->qf_sap);
+	RW_EXIT(&pfil_rw);
+
+	READ_ENTER(&pfh_sync.ph_lock);
+
+	pfh = pfil_hook_get(PFIL_IN, &pfh_sync);
+	for (; pfh; pfh = pfh->pfil_next)
+		if (pfh->pfil_func)
+			(void) (*pfh->pfil_func)(NULL, 0, qif, 0, qif, NULL);
+
+	RW_EXIT(&pfh_sync.ph_lock);
+
+	if (qif_verbose > 0)
+		cmn_err(CE_NOTE, "PFIL: attaching [%s] - %s", qif->qf_name,
+			SAPNAME(qif));
+#if SOLARIS2 <= 8
+	ire_walk(qif_ire_walker, qif);
+#else
+# ifndef IRE_ILL_CN
+	ire_walk(qif_ire_walker, (char *)qif);
+# endif
+#endif
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    qif_new                                                     */
+/* Returns:     qif_t * - NULL == failure, else pointer to qif_t            */
+/* Parameters:  q(I) - pointer to STREAMS queue                             */
+/*                                                                          */
+/* Allocate a new qif struct, give it a unique number and add it to the     */
+/* list of registered qif_t's for the given queue.  Along the way, if we    */
+/* find an existing qif_t for this queue, return that instead.              */
+/* ------------------------------------------------------------------------ */
+qif_t *
+qif_new(q, mflags)
+	queue_t *q;
+	int mflags;
+{
+	qif_t *qif;
+
+	qif = kmem_cache_alloc(qif_cache, mflags);
+	if (qif == NULL) {
+		cmn_err(CE_NOTE, "PFIL: malloc(%d) for qif_t failed",
+			(int)sizeof(qif_t));
+		return NULL;
+	}
+
+	bzero((char *)qif, sizeof(*qif));
+	mutex_init(&qif->qf_ptl.pt_lock, NULL, MUTEX_DRIVER, NULL);
+	cv_init(&qif->qf_ptl.pt_cv, NULL, CV_DRIVER, NULL);
+	qif->qf_qifsz = sizeof(*qif);
+	qif->qf_q = q;
+	qif->qf_oq = OTHERQ(q);
+	WRITE_ENTER(&pfil_rw);
+	qif->qf_num = qif_num++;
+	qif->qf_next = qif_head;
+	qif_head = qif;
+	RW_EXIT(&pfil_rw);
+	(void) sprintf(qif->qf_name, "QIF%x", qif->qf_num);
+	return qif;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    qif_delete                                                  */
+/* Returns:     void                                                        */
+/* Parameters:  None.                                                       */
+/* Write Locks: pfil_rw                                                     */
+/*                                                                          */
+/* Remove a qif structure from the list of recognised qif's.                */
+/*                                                                          */
+/* NOTE: The locking structure used here on qif's is to protect their use   */
+/* by the pkt.c functions for sending out a packet.  It is possible that a  */
+/* packet will be processed on one queue and need to be output on another   */
+/* and given we cannot hold a lock across putnext() we need to use a P-V    */
+/* like algorithm for locking.  The PT_* macros come from the PTY code.     */
+/* In the fullness of time, this function should be rewritten to make sure  */
+/* that it is not posible to find the qif before we call the PT_* macros    */
+/* and call qprocsoff().                                                    */
+/* ------------------------------------------------------------------------ */
+/*ARGSUSED*/
+void qif_delete(qif, q)
+qif_t *qif;
+queue_t *q;
+{
+	packet_filter_hook_t *pfh;
+	qif_t **qp;
+	int rm = 0;
+
+	if (qif == NULL)
+		return;
+
+	WRITE_ENTER(&pfil_rw);
+	PT_ENTER_WRITE(&qif->qf_ptl);
+
+	if (qif->qf_bound == 1 && qif_verbose > 0)
+		cmn_err(CE_NOTE, "PFIL: detaching [%s] - %s", qif->qf_name,
+			SAPNAME(qif));
+
+	for (qp = &qif_head; *qp; qp = &(*qp)->qf_next)
+		if (*qp == qif) {
+			*qp = qif->qf_next;
+			rm = 1;
+			break;
+		}
+	PT_EXIT_WRITE(&qif->qf_ptl);
+	RW_EXIT(&pfil_rw);
+
+	if (qif->qf_ill) {
+		READ_ENTER(&pfh_sync.ph_lock);
+		pfh = pfil_hook_get(PFIL_OUT, &pfh_sync);
+		for (; pfh; pfh = pfh->pfil_next)
+			if (pfh->pfil_func)
+				(void) (*pfh->pfil_func)(NULL, 0, qif,
+							 1, qif, NULL);
+		RW_EXIT(&pfh_sync.ph_lock);
+	}
+
+	if (rm) {
+		if (qif->qf_addrset != NULL)
+			freeb(qif->qf_addrset);
+		mutex_destroy(&qif->qf_ptl.pt_lock);
+		cv_destroy(&qif->qf_ptl.pt_cv);
+
+		if (qif->qf_qifsz == sizeof(*qif))
+			kmem_cache_free(qif_cache, qif);
+		else {
+			KMFREE(qif, qif->qf_qifsz);
+		}
+	}
+	return;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    qif_iflookup                                                */
+/* Returns:     void *  - NULL == search failed, else pointer to qif_t      */
+/* Parameters:  name(I) - pointer to the name                               */
+/*              sap(I)  - SAP value                                         */
+/* Locks:       pfil_rw                                                     */
+/*                                                                          */
+/* Search the list of registered qif_t's for a match based on the name and  */
+/* the SAP and return a pointer to the matching entry.                      */
+/* ------------------------------------------------------------------------ */
+void *qif_iflookup(char *name, int sap)
+{
+	qif_t *qif;
+
+	for (qif = qif_head; qif; qif = qif->qf_next)
+		if ((!sap || (qif->qf_sap == sap)) &&
+		    !strcmp(qif->qf_name, name))
+			break;
+	return qif;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    qif_update                                                  */
+/* Returns:     void                                                        */
+/* Parameters:  qif(I) - pointer to qif_t structure                         */
+/*              mp(I)  - pointer to STREAMS message                         */
+/* Locks:       pfil_rw                                                     */
+/*                                                                          */
+/* This function attempts to force an update of the qf_sap and qf_hl fields */
+/* using information that is in the STREAMS message and/or the ill_t.  This */
+/* function should only be called if the mblk is a DL_IOC_HDR_INFO message. */
+/* ------------------------------------------------------------------------ */
+void qif_update(qif, mp)
+qif_t *qif;
+mblk_t *mp;
+{
+#ifdef IRE_ILL_CN
+	s_ill_t *ill;
+#else
+	ill_t *ill;
+#endif
+
+	ill = qif->qf_ill;
+	if (ill == NULL)
+		return;
+
+	if (mp->b_datap->db_type == M_IOCACK && mp->b_cont) {
+		mp = mp->b_cont;
+		if (mp->b_datap->db_type == M_PROTO && mp->b_cont) {
+			mp = mp->b_cont;
+			if (mp->b_datap->db_type == M_DATA) {
+				qif->qf_hl = mp->b_wptr - mp->b_rptr;
+			}
+		}
+	}
+
+	/*
+	 * If we still have a 0 size expected fasthpath header length, check
+	 * the ill structure to see if we can use it to now make a better
+	 * guess about what to use.
+	 */
+	qif->qf_sap = ill->ill_sap;
+#ifndef IRE_ILL_CN
+	if (qif->qf_hl == 0) {
+#if SOLARIS2 < 8
+		qif->qf_hl = ill->ill_hdr_length;
+#else
+		if ((ill->ill_type > 0) && (ill->ill_type < 0x37) &&
+		    (hdrsizes[ill->ill_type][0] == ill->ill_type))
+			qif->qf_hl = hdrsizes[ill->ill_type][1];
+#endif
+	}
+#endif
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    qif_walk                                                    */
+/* Returns:     qif_t *  - NULL == search failed, else pointer to qif_t     */
+/* Parameters:  qfp(IO) - pointer to the name                               */
+/*                                                                          */
+/* NOTE: it is assumed the caller has a lock on pfil_rw                     */
+/*                                                                          */
+/* Provide a function to enable the caller to enumerate through all of the  */
+/* qif_t's without being aware of the internal data structure used to store */
+/* them in.                                                                 */
+/* ------------------------------------------------------------------------ */
+qif_t *qif_walk(qif_t **qfp)
+{
+	struct qif *qf, *qf2;
+
+	if (qfp == NULL)
+		return NULL;
+
+	qf = *qfp;
+	if (qf == NULL)
+		*qfp = qif_head;
+	else {
+		/*
+		 * Make sure the pointer being passed in exists as a current
+		 * object before returning its next value.
+		 */
+		for (qf2 = qif_head; qf2 != NULL; qf2 = qf2->qf_next)
+			if (qf2 == qf)
+				break;
+		if (qf2 == NULL)
+			*qfp = NULL;
+		else
+			*qfp = qf->qf_next;
+	}
+	return *qfp;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    qif_ipmp_update                                             */
+/* Returns:     void                                                        */
+/* Parameters:  ipmpconf(I) - pointer to an ill to match against            */
+/*                                                                          */
+/* Take an IPMP configuration string passed in to update the pfil config.   */
+/* The string may either indicate that an IPMP interface is to be deleted   */
+/* ("ipmp0=" - no NICs after the right of the '=') or created/changed if    */
+/* there is text after the '='.                                             */
+/* ------------------------------------------------------------------------ */
+void qif_ipmp_update(char *ipmpconf)
+{
+	qif_t *qif, *qf;
+	int len, sap;
+	char *s;
+
+	sap = ETHERTYPE_IP;
+	if (!strncmp(ipmpconf, "v4:", 3)) {
+		ipmpconf += 3;
+	} else if (!strncmp(ipmpconf, "v6:", 3)) {
+#if SOLARIS2 >= 8
+		sap = IP6_DL_SAP;
+		ipmpconf += 3;
+#else
+		return;
+#endif
+	}
+
+	s = strchr(ipmpconf, '=');
+	if (s != NULL) {
+		if (*(s + 1) == '\0')
+			*s = '\0';
+		else
+			*s++ = '\0';
+	}
+	if (s == NULL || *s == NULL) {
+		qif_ipmp_delete(ipmpconf);
+		return;
+	}
+
+	len = sizeof(qif_t) + strlen(s) + 1;
+	KMALLOC(qif, qif_t *, len, KM_NOSLEEP);
+	if (qif == NULL) {
+		cmn_err(CE_NOTE, "PFIL: malloc(%d) for qif_t failed", len);
+		return;
+	}
+
+	WRITE_ENTER(&pfil_rw);
+	for (qf = qif_head; qf; qf = qf->qf_next) 
+		if (strcmp(qf->qf_name, ipmpconf) == 0)
+			break;
+
+	if (qf == NULL) {
+		qf = qif;
+		qif->qf_next = qif_head;
+		qif_head = qif;
+
+		qif->qf_sap = sap;
+		qif->qf_flags |= QF_IPMP;
+		qif->qf_qifsz = len;
+		qif->qf_members = (char *)qif + sizeof(*qif);
+		(void) strcpy(qif->qf_name, ipmpconf);
+	} else {
+		KMFREE(qif, len);
+		qif = qf;
+	}
+
+	(void) strcpy(qif->qf_members, s);
+
+	qif_ipmp_syncmaster(qif, sap);
+
+	RW_EXIT(&pfil_rw);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    qif_ipmp_delete                                             */
+/* Returns:     void                                                        */
+/* Parameters:  qifname(I) - pointer to name of qif to delete               */
+/*                                                                          */
+/* Search for a qif structure that is named to match qifname, remove all    */
+/* references to it by others, delink and free it.                          */
+/* ------------------------------------------------------------------------ */
+void qif_ipmp_delete(char *qifname)
+{
+	packet_filter_hook_t *pfh;
+	qif_t *qf, **qfp, *qif;
+
+	WRITE_ENTER(&pfil_rw);
+	for (qfp = &qif_head; (qif = *qfp) != NULL; qfp = &qif->qf_next) {
+		if ((qif->qf_flags & QF_IPMP) == 0)
+			continue;
+		if (strcmp(qif->qf_name, qifname) == 0) {
+			*qfp = qif->qf_next;
+			for (qf = qif_head; qf != NULL; qf = qf->qf_next)
+				if (qf->qf_ipmp == qif)
+					qf->qf_ipmp = NULL;
+			break;
+		}
+	}
+	RW_EXIT(&pfil_rw);
+
+	if (qif != NULL) {
+		pfh = pfil_hook_get(PFIL_OUT, &pfh_sync);
+		for (; pfh; pfh = pfh->pfil_next)
+			if (pfh->pfil_func)
+				(void) (*pfh->pfil_func)(NULL, 0, qif, 1,
+							 qif, NULL);
+
+		KMFREE(qif, qif->qf_qifsz);
+	}
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    qif_ipmp_syncmaster                                         */
+/* Returns:     void                                                        */
+/* Parameters:  updated(I) - pointer to updated qif structure               */
+/* Locks:       pfil_rw                                                     */
+/*                                                                          */
+/* This function rechecks all the qif structures that aren't defined for    */
+/* IPMP to see if they are indeed members of the group pointed to by        */
+/* updated.  Ones that currently claim to be in updated are reset and       */
+/* rechecked in case they have become excluded. This function should be     */
+/* called for any new IPMP qif's created or when an IPMP qif changes.       */
+/* ------------------------------------------------------------------------ */
+void qif_ipmp_syncmaster(qif_t *updated, const int sap)
+{
+	char *s, *t;
+	qif_t *qf;
+
+	for (qf = qif_head; qf != NULL; qf = qf->qf_next)  {
+		if ((qf->qf_flags & QF_IPMP) != 0)
+			continue;
+		if (qf->qf_sap != sap)
+			continue;
+		if (qf->qf_ipmp == updated)
+			qf->qf_ipmp = NULL;
+		for (s = updated->qf_members; s != NULL; ) {
+			t = strchr(s, ',');
+			if (t != NULL)
+				*t = '\0';
+			if (strcmp(qf->qf_name, s) == 0)
+				qf->qf_ipmp = updated;
+			if (t != NULL)
+				*t++ = ',';
+			s = t;
+		}
+	}
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    qif_ipmp_syncslave                                          */
+/* Returns:     void                                                        */
+/* Parameters:  target(I) - pointer to updated qif structure                */
+/* Locks:       pfil_rw                                                     */
+/*                                                                          */
+/* Check through the list of qif's to see if there is an IPMP with a member */
+/* list that includes the one named by target.                              */
+/* ------------------------------------------------------------------------ */
+void qif_ipmp_syncslave(qif_t *target, const int sap)
+{
+	char *s, *t;
+	qif_t *qf;
+
+	target->qf_ipmp = NULL;
+
+	/*
+	 * Recheck the entire list of qif's for any references to the one
+	 * we have just created/updated (updated).
+	 */
+	for (qf = qif_head; qf != NULL; qf = qf->qf_next)  {
+		if ((qf->qf_flags & QF_IPMP) == 0)
+			continue;
+		if (qf->qf_sap != sap)
+			continue;
+		for (s = qf->qf_members; s != NULL; ) {
+			t = strchr(s, ',');
+			if (t != NULL)
+				*t = '\0';
+			if (strcmp(target->qf_name, s) == 0)
+				target->qf_ipmp = qf;
+			if (t != NULL)
+				*t++ = ',';
+			s = t;
+			if (target->qf_ipmp == qf)
+				break;
+		}
+	}
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    qif_hl_set                                                  */
+/* Returns:     void                                                        */
+/* Parameters:  ipmpconf(I) - string with header length setting for NIC     */
+/*                                                                          */
+/* For NICs that we cannot automatically determine the MAC header length of */
+/* we provide a manual crook to achieve that with.  The input syntax for    */
+/* the string is "[v4:|v6:]<ifname>=<length>"                               */
+/* ------------------------------------------------------------------------ */
+void qif_hl_set(char *ipmpconf)
+{
+	qif_t *qf;
+	char *s;
+
+	if (!strncmp(ipmpconf, "v4:", 3)) {
+		ipmpconf += 3;
+	} else if (!strncmp(ipmpconf, "v6:", 3)) {
+#if SOLARIS2 >= 8
+		ipmpconf += 3;
+#else
+		return;
+#endif
+	}
+
+	s = strchr(ipmpconf, '=');
+	if (s != NULL) {
+		if (*(s + 1) == '\0')
+			*s = '\0';
+		else
+			*s++ = '\0';
+	}
+	if (s == NULL || *s == NULL)
+		return;
+
+	READ_ENTER(&pfil_rw);
+	for (qf = qif_head; qf; qf = qf->qf_next) 
+		if (strcmp(qf->qf_name, ipmpconf) == 0)
+			break;
+
+	if (qf != NULL) {
+		int hl = 0;
+
+		for (; *s != '\0'; s++) {
+			char c = *s;
+
+			if (c < '0' || c > '9')
+				return;
+			hl *= 10;
+			hl += c - '0'; 
+		}
+		qf->qf_hl = hl;
+	}
+
+	RW_EXIT(&pfil_rw);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/uts/common/inet/pfil/qif.h	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef sun
+# include <sys/dditypes.h>
+# include <sys/ptms.h>
+#endif
+
+
+#ifdef	IRE_ILL_CN
+typedef	union	{
+	struct sockaddr_in qfa_in;
+	struct sockaddr_in6 qfa_in6;
+} qfa_t;
+# define	qfa_family	qfa_in.sin_family
+# define	qfa_v4addr	qfa_in.sin_addr
+# define	qfa_v6addr	qfa_in6.sin6_addr
+#else
+# define	QF_IPIF(x)	((ill_t *)(x)->qf_ill)->ill_ipif
+# define	qf_netmask	QF_IPIF->ipif_net_mask
+#  define	qf_dstaddr	QF_IPIF->ipif_pp_dst_addr
+# if SOLARIS2 <= 7
+#  define	qf_localaddr	QF_IPIF->ipif_local_addr
+#  define	qf_broadaddr	QF_IPIF->ipif_broadcast_addr
+# else
+#  define	qf_localaddr	QF_IPIF->ipif_lcl_addr
+#  define	qf_broadaddr	QF_IPIF->ipif_brd_addr
+# endif
+# ifdef	USE_INET6
+#  define	qf_v6netmask	QF_IPIF->ipif_v6net_mask
+#  define	qf_v6broadaddr	QF_IPIF->ipif_v6brd_addr
+#  define	qf_v6dstaddr	QF_IPIF->ipif_v6pp_dst_addr
+# endif
+#endif
+
+typedef	struct	s_ill_s	{
+	struct	s_ill_s	*ill_next;	/* Chained in at s_ill_g_head. */
+	kmutex_t	s_ill_lock;
+	char	ill_name[LIFNAMSIZ];	/* Our name. */
+	t_uscalar_t	ill_sap;	/* IP_DL_SAP or IP6_DL_SAP */
+	queue_t	*ill_rq;		/* lower stream read queue */
+	union {
+		struct sockaddr_in in;
+		struct sockaddr_in6 in6;
+	} localaddr;
+	union {
+		struct sockaddr_in in;
+		struct sockaddr_in6 in6;
+	} netmask;
+	union {
+		struct sockaddr_in in;
+		struct sockaddr_in6 in6;
+	} broadaddr;
+	union {
+		struct sockaddr_in in;
+		struct sockaddr_in6 in6;
+	} dstaddr;
+	uint_t	mtu;
+} s_ill_t;
+
+typedef	struct	qif	{
+	/* for alignment reasons, the lock is first. */
+	kmutex_t	qf_lock;
+	struct qifplock {
+		kmutex_t	pt_lock;
+#ifdef sun
+		kcondvar_t	pt_cv;
+#endif
+		int		pt_refcnt;
+		int		pt_access;
+	} qf_ptl;
+	struct	qif	*qf_next;
+	struct	qif	*qf_ipmp;	/* Pointer to group qif */
+	void		*qf_ill;
+	queue_t		*qf_q;
+	queue_t		*qf_oq;
+	/* statistical data */
+	u_long		qf_nr;
+	u_long		qf_nw;
+	u_long		qf_bad;
+	u_long		qf_copy;
+	u_long		qf_copyfail;
+	u_long		qf_drop;
+	u_long		qf_notip;
+	u_long		qf_nodata;
+	u_long		qf_notdata;
+	/* other data for the NIC on this queue */
+	size_t		qf_qifsz;
+	size_t		qf_hl;		/* header length */
+	u_int		qf_num;
+	u_int		qf_ppa;		/* Physical Point of Attachment */
+	int		qf_sap;		/* Service Access Point */
+	int		qf_bound;
+	int		qf_flags;
+	int		qf_waitack;
+	int		qf_max_frag;	/* MTU for interface */
+	char		qf_name[LIFNAMSIZ];
+	char		*qf_members;
+
+	/* ON(10, NV) specific */
+	mblk_t		*qf_addrset;
+	size_t		qf_off;
+	mblk_t		*qf_m;
+	void		*qf_data;
+} qif_t;
+
+
+typedef	struct	qpktinfo	{
+	/* data that changes per-packet */
+	qif_t		*qpi_real;	/* the real one on the STREAM */
+	void		*qpi_ill;	/* COPIED */
+	mblk_t		*qpi_m;
+	queue_t		*qpi_q;
+	char		*qpi_name;	/* points to qf_real->qf_name */
+	void		*qpi_data;	/* where layer 3 header starts */
+	size_t		qpi_off;
+	size_t		qpi_hl;		/* COPIED */
+	u_int		qpi_ppa;	/* COPIED */
+	u_int		qpi_num;	/* COPIED */
+	int		qpi_flags;	/* COPIED */
+	int		qpi_max_frag;	/* COPIED */
+} qpktinfo_t;
+
+
+#ifdef sun
+# if SOLARIS2 <= 7
+#  define	QF_V4_ADDR(x)	\
+			((ill_t *)(x)->qf_ill)->ill_ipif->ipif_local_addr
+#  define	QF_V4_BROADCAST(x)	\
+			((ill_t *)(x)->qf_ill)->ill_ipif->ipif_broadcast_addr
+# else
+#  define	QF_V4_ADDR(x)	\
+			((ill_t *)(x)->qf_ill)->ill_ipif->ipif_lcl_addr
+#  define	QF_V4_BROADCAST(x)	\
+			((ill_t *)(x)->qf_ill)->ill_ipif->ipif_brd_addr
+# endif
+# define	QF_V4_NETMASK(x)	\
+			((ill_t *)(x)->qf_ill)->ill_ipif->ipif_net_mask
+# define	QF_V4_PEERADDR(x)	\
+			((ill_t *)(x)->qf_ill)->ill_ipif->ipif_pp_dst_addr
+# ifdef	USE_INET6
+#  define	QF_V6_BROADCAST(x)	\
+			((ill_t *)(x)->qf_ill)->ill_ipif->ipif_v6brd_addr
+#  define	QF_V6_NETMASK(x)	\
+			((ill_t *)(x)->qf_ill)->ill_ipif->ipif_v6net_mask
+#  define	QF_V6_PEERADDR(x)	\
+			((ill_t *)(x)->qf_ill)->ill_ipif->ipif_v6pp_dst_addr
+# endif
+#endif
+
+#ifdef __hpux
+# define	QF_V4_ADDR(x)		((ifinfo_t *)(x)->qf_ill)->ifi_addr[0]
+# define	QF_V4_BROADCAST(x)	0
+# define	QF_V4_NETMASK(x)	0xffffffff
+# define	QF_V4_PEERADDR(x)	0
+# ifdef	USE_INET6
+#  define	QF_V6_BROADCAST(x)	0
+#  define	QF_V6_NETMASK(x)	0
+#  define	QF_V6_PEERADDR(x)	0
+# endif
+#endif
+
+
+#define	QF_GROUP	0x0001
+#define	QF_IPMP		0x0002
+
+extern void *q_to_ill(queue_t *);
+extern struct qif *qif_new(queue_t *, int);
+extern int qif_attach(queue_t *);
+extern void qif_delete(struct qif *, queue_t *);
+extern int qif_startup(void);
+extern void qif_stop(void);
+extern void *qif_iflookup(char *, int);
+
+#ifdef __hpux
+struct irinfo_s;
+extern void *ir_to_ill(struct irinfo_s *ir);
+#endif
+extern struct qif *qif_walk(struct qif **);
+extern struct qif *qif_head;
+extern int qif_verbose;
+extern void qif_update(struct qif *, mblk_t *);
+extern void qif_nd_init(void);
+extern void qif_hl_set(char *);
+extern void qif_ipmp_delete(char *);
+extern void qif_ipmp_update(char *);
+extern void qif_ipmp_syncmaster(struct qif *, const int);
+extern void qif_ipmp_syncslave(struct qif *, const int);
+
+#ifndef IRE_ILL_CN
+extern void qif_ire_walker(ire_t *, void *);
+#endif
+
+extern kmutex_t s_ill_g_head_lock;
+extern s_ill_t *s_ill_g_head;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/uts/intel/pfil/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,93 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+#
+# uts/intel/pfil/Makefile
+#
+#	This makefile drives the production of the pfil driver 
+#	kernel module.
+#
+#	intel architecture dependent
+#
+
+#
+#	Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE	= ../..
+
+#
+#	Define the module and object file sets.
+#
+MODULE		= pfil
+OBJECTS		= $(PFIL_OBJS:%=$(OBJS_DIR)/%)
+LINTS		= $(PFIL_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE	= $(ROOT_DRV_DIR)/$(MODULE)
+ROOTLINK	= $(ROOT_STRMOD_DIR)/$(MODULE)
+CONF_SRCDIR	= $(UTSBASE)/common/inet/pfil
+
+#
+#	Include common rules.
+#
+include $(UTSBASE)/intel/Makefile.intel
+
+#
+#	Define targets
+#
+ALL_TARGET	= $(BINARY) $(SRC_CONFFILE)
+LINT_TARGET	= $(MODULE).lint
+INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOTLINK) $(ROOT_CONFFILE)
+
+MINOR=       echo $(RELEASE) | cut -d. -f2
+CPPFLAGS +=  -DSUNDDI -DSOLARIS2=$(MINOR:sh) -DIRE_ILL_CN -DSOLARIS -DUSE_INET6
+LDFLAGS += -dy -Ndrv/ip 
+
+#
+#	Default build targets.
+#
+.KEEP_STATE:
+
+def:		$(DEF_DEPS)
+
+all:		$(ALL_DEPS)
+
+clean:		$(CLEAN_DEPS)
+
+clobber:	$(CLOBBER_DEPS)
+
+lint:		$(LINT_DEPS)
+
+modlintlib:	$(MODLINTLIB_DEPS)
+
+clean.lint:	$(CLEAN_LINT_DEPS)
+
+install:	$(INSTALL_DEPS)
+
+$(ROOTLINK):	$(ROOT_STRMOD_DIR) $(ROOTMODULE)
+	-$(RM) $@; ln $(ROOTMODULE) $@
+
+#
+#	Include common targets.
+#
+include $(UTSBASE)/intel/Makefile.targ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/uts/sparc/pfil/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,97 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+#
+# uts/sparc/pfil/Makefile
+#
+#	This makefile drives the production of the pfil driver 
+#	kernel module.
+#
+#	sparc architecture dependent
+#
+
+#
+#	Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE	= ../..
+
+#
+#	Define the module and object file sets.
+#
+MODULE		= pfil
+OBJECTS		= $(PFIL_OBJS:%=$(OBJS_DIR)/%)
+LINTS		= $(PFIL_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE	= $(ROOT_DRV_DIR)/$(MODULE)
+ROOTLINK	= $(ROOT_STRMOD_DIR)/$(MODULE)
+CONF_SRCDIR	= $(UTSBASE)/common/inet/pfil
+
+#
+#	Include common rules.
+#
+include $(UTSBASE)/sparc/Makefile.sparc
+
+#
+#	Define targets
+#
+ALL_TARGET	= $(BINARY) $(SRC_CONFFILE)
+LINT_TARGET	= $(MODULE).lint
+INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOTLINK) $(ROOT_CONFFILE)
+
+#
+# lint pass one enforcement and OS version
+#
+MINOR=    echo $(RELEASE) | cut -d. -f2
+CFLAGS += $(CCVERBOSE)
+CPPFLAGS +=  -DSUNDDI -DSOLARIS2=$(MINOR:sh) -DIRE_ILL_CN -DSOLARIS -DUSE_INET6
+LDFLAGS += -dy -Ndrv/ip
+
+#
+#	Default build targets.
+#
+.KEEP_STATE:
+
+def:		$(DEF_DEPS)
+
+all:		$(ALL_DEPS)
+
+clean:		$(CLEAN_DEPS)
+
+clobber:	$(CLOBBER_DEPS)
+
+lint:		$(LINT_DEPS)
+
+modlintlib:	$(MODLINTLIB_DEPS) lint64
+
+clean.lint:	$(CLEAN_LINT_DEPS)
+
+install:	$(INSTALL_DEPS)
+
+$(ROOTLINK):	$(ROOT_STRMOD_DIR) $(ROOTMODULE)
+	-$(RM) $@; ln $(ROOTMODULE) $@
+
+#
+#	Include common targets.
+#
+include $(UTSBASE)/sparc/Makefile.targ
--- a/usr/src/cmd/devfsadm/misc_link.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/cmd/devfsadm/misc_link.c	Fri Oct 20 16:37:58 2006 -0700
@@ -110,7 +110,7 @@
 	    TYPE_EXACT | DRV_RE, ILEVEL_1, minor_name
 	},
 	{ "pseudo", "ddi_pseudo",
-	    "(^pfil$)|(^ipf$)|(^ipnat$)|(^ipstate$)|(^ipauth$)|"
+	    "(^ipf$)|(^ipnat$)|(^ipstate$)|(^ipauth$)|"
 	    "(^ipsync$)|(^ipscan$)|(^iplookup$)",
 	    TYPE_EXACT | DRV_RE, ILEVEL_0, minor_name,
 	},
--- a/usr/src/cmd/ipf/Makefile	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/cmd/ipf/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -1,5 +1,25 @@
 #
-# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
@@ -9,7 +29,7 @@
 
 SUBDIRS=	etc examples \
 		lib svc .WAIT \
-		pfild tools
+		tools
 
 LINTCLEAN=
 LINTSUBDIRS=
--- a/usr/src/cmd/ipf/etc/Makefile	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/cmd/ipf/etc/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -1,5 +1,25 @@
 #
-# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
@@ -7,9 +27,8 @@
 #cmd/ipf/etc/Makefile
 #
 
-PFILAP=		pfil.ap
 IPFCONF=	ipf.conf
-IPFPROG=	$(PFILAP) $(IPFCONF)
+IPFPROG=	$(IPFCONF)
 
 include ../../Makefile.cmd
 
--- a/usr/src/cmd/ipf/etc/pfil.ap.sh	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-#!/sbin/sh
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-
-#ident	"%Z%%M%	%I%	%E% SMI"
-
-case "$MACH" in
-  "i386" )
-	echo "# IP Filter pfil autopush setup
-#
-# See the autopush(1M) manpage for more information.
-#
-# Format of the entries in this file is:
-#
-#major  minor lastminor modules
-
-#iprb	-1	0	pfil
-#elxl	-1	0	pfil
-#e1000g	-1	0	pfil
-#bge	-1	0	pfil
-#nf	-1	0	pfil
-#fa	-1	0	pfil
-#ci	-1	0	pfil
-#el	-1	0	pfil
-#ipdptp	-1	0	pfil
-#lane	-1	0	pfil
-#dnet	-1	0	pfil
-#pcelx	-1	0	pfil
-#spwr	-1	0	pfil
-#ce	-1	0	pfil
-
-" > pfil.ap
-	;;
-  "sparc" )
-	echo "# IP Filter pfil autopush setup
-#
-# See autopush(1M) manpage for more information.
-#
-# Format of the entries in this file is:
-#
-#major  minor lastminor modules
-
-#le	-1	0	pfil
-#qe	-1	0	pfil
-#hme	-1	0	pfil
-#qfe	-1	0	pfil
-#eri	-1	0	pfil
-#ce	-1	0	pfil
-#e1000g	-1	0	pfil
-#bge	-1	0	pfil
-#be	-1	0	pfil
-#vge	-1	0	pfil
-#ge	-1	0	pfil
-#nf	-1	0	pfil
-#fa	-1	0	pfil
-#ci	-1	0	pfil
-#el	-1	0	pfil
-#ipdptp	-1	0	pfil
-#lane	-1	0	pfil
-#dmfe	-1	0	pfil
-" >pfil.ap
-	;;
-  * )
-	echo "Unknown architecture."
-	exit 1
-	;;
-esac
-
--- a/usr/src/cmd/ipf/lib/common/getifname.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/cmd/ipf/lib/common/getifname.c	Fri Oct 20 16:37:58 2006 -0700
@@ -10,17 +10,19 @@
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include "ipf.h"
-#include "qif.h"
 #include "kmem.h"
 
 /*
  * Given a pointer to an interface in the kernel, return a pointer to a
  * string which is the interface name.
+ *
+ * The same code is used to run in two different environments: in ipfstat
+ * and in ipftest.  In ipftest, kmemcpy is wrapper for bcopy but in ipfstat,
+ * it is used as an interface to libkvm.
  */
 char *getifname(ptr)
 struct ifnet *ptr;
 {
-#if SOLARIS || defined(__hpux)
 # if SOLARIS
 #  include <sys/mutex.h>
 #  include <sys/condvar.h>
@@ -28,23 +30,6 @@
 # ifdef __hpux
 #  include "compat.h"
 # endif
-	char *ifname;
-	qif_t qif;
-
-	if ((void *)ptr == (void *)-1)
-		return "!";
-	if (ptr == NULL)
-		return "-";
-
-	if (kmemcpy((char *)&qif, (u_long)ptr, sizeof(qif)) == -1)
-		return "X";
-	ifname = strdup(qif.qf_name);
-	if ((ifname != NULL) && (*ifname == '\0')) {
-		free(ifname);
-		return "!";
-	}
-	return ifname;
-#else
 # if defined(NetBSD) && (NetBSD >= 199905) && (NetBSD < 1991011) || \
     defined(__OpenBSD__) || \
     (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
@@ -54,6 +39,11 @@
 # endif
 	struct ifnet netif;
 
+# ifdef SOLARIS_PFHOOKS
+	if ((opts & OPT_DONOTHING) == 0)
+		return "@";
+# endif
+
 	if ((void *)ptr == (void *)-1)
 		return "!";
 	if (ptr == NULL)
@@ -80,5 +70,4 @@
 	sprintf(buf + strlen(buf), "%d", netif.if_unit % 10000);
 	return strdup(buf);
 # endif
-#endif
 }
--- a/usr/src/cmd/ipf/lib/common/getsumd.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/cmd/ipf/lib/common/getsumd.c	Fri Oct 20 16:37:58 2006 -0700
@@ -1,3 +1,15 @@
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
 #include "ipf.h"
 
 char *getsumd(sum)
@@ -5,9 +17,6 @@
 {
 	static char sumdbuf[17];
 
-	if (sum & NAT_HW_CKSUM)
-		sprintf(sumdbuf, "hw(%#0x)", sum & 0xffff);
-	else
-		sprintf(sumdbuf, "%#0x", sum);
+	sprintf(sumdbuf, "%#0x", sum);
 	return sumdbuf;
 }
--- a/usr/src/cmd/ipf/pfild/Makefile	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-#
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-PROG=	pfild
-
-OBJS=	pfild.o vas.o
-SRCS=	$(OBJS:.o=.c)
-
-include ../../Makefile.cmd
-include ../Makefile.ipf
-
-LDLIBS          += $(LIBBPF) -lsocket -lnsl
-CFLAGS		+= -DNDEBUG -D_XOPEN_SOURCE=500 -D__EXTENSIONS__
-CPPFLAGS        += -I. -DIPFILTER_LOOKUP -DIPFILTER_LOG
-CLEANFILES	+= $(OBJS)
-
-.KEEP_STATE:
-
-all: $(PROG)
-
-$(PROG): $(OBJS)
-	$(LINK.c) $(OBJS) -o $@ $(LDLIBS)
-	$(POST_PROCESS)
-
-install: all $(ROOTUSRSBINPROG)
-
-clean:
-	-$(RM) $(OBJS) $(PROG)
-
-lint:	lint_SRCS
-
-include ../../Makefile.targ
--- a/usr/src/cmd/ipf/pfild/pfild.c	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,616 +0,0 @@
-/*
- * Copyright (C) 2003 by Darren Reed.
- *
- * See the IPFILTER.LICENCE file for details on licencing.
- *
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <net/if.h>
-#include <net/route.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <poll.h>
-#include <stdio.h>
-#include <malloc.h>
-#include <stropts.h>
-#include <stdlib.h>
-#include <netinet/ip.h>
-#include <netinet/ip6.h>
-#include <netinet/icmp6.h>
-#include "pfild.h"
-
-extern int vas(const struct pfil_ifaddrs *, int);
-
-/*
- * pfild.c:  interface data and packet transmission daemon for pfil
- *
- * pfild provides the pfil kernel module with certain data that are not
- * directly available to kernel code using supported OS interfaces.  pfild
- * accesses the routing tables and network interface parameters using
- * interfaces readily available to a user space daemon, copies the data into
- * the kernel via /dev/pfil, and waits for any changes to the data.
- *
- * pfild also provides a way for the kernel module to originate IP packets
- * without resorting to unsupported kernel interfaces.  If the kernel
- * sends up an M_DATA message, pfild sends it on a raw IP socket so that it
- * gets routed and transmitted as a normal packet.
- */
-
-
-/* file descriptors for talking to pfil, ifnet, routing kernel modules */
-static int pfil_fd, ip_fd, icmp6_ip6_fd, tcp_ip6_fd, route_fd;
-
-/*
- * flag indicates that some interface or routing data have changed since
- * last update.
- */
-static int flag = 1;
-/*
- * debuglevel indicates to what level debugging messages should be emitted.
- */
-static int debuglevel = 0;
-
-/* Wait for this many ms of quiet time after changes before doing an update. */
-#define	QUIETTIME 200
-
-
-/*
- * Send a message to the pfil kernel module.
- * Returns zero for success, otherwise non-zero with errror in errno.
- */
-int
-pfil_msg(uint32_t cmd, void *buf, size_t len)
-{
-	int error;
-
-	if (debuglevel > 0)
-		(void) fprintf(stderr, "pfil_msg(%x,%p,%d)\n", cmd, buf, len);
-
-	if (pfil_fd >= 0) {
-		struct strbuf ctl, data;
-
-		ctl.buf = (void *)&cmd;
-		ctl.len = sizeof (cmd);
-		data.buf = buf;
-		data.len = len;
-
-		error = putmsg(pfil_fd, &ctl, &data, 0);
-		if (debuglevel > 0)
-			(void) fprintf(stderr,
-			    "pfild:pfil_msg():putmsg(%d,%p,%p,0) = %d\n",
-			    pfil_fd, &ctl, &data, 0, error);
-	} else {
-		error = 0;
-		if (debuglevel > 0)
-			(void) fprintf(stderr,
-			    "pfild:pfil_msg():pfil_fd < 0\n");
-	}
-
-	return (error);
-}
-
-
-/*
- * Handle a PF_ROUTE message.  If an address has been added or deleted, treat
- * this as an indication that some interface data has been udpated.  If a route
- * has been added or deleted, treat this as an indication that the routing
- * table has been updated.  The current implementation completely updates both
- * sets of data when either kind of change is indicated.
- *
- * p points to, and size indicates the size of, the message.
- */
-static void
-handle_msg(const ifa_msghdr_t *p, size_t size)
-{
-	if (size < sizeof (*p) ||
-	    size < p->ifam_msglen ||
-	    p->ifam_version != RTM_VERSION) {
-		if (debuglevel > 0)
-			(void) fprintf(stderr,
-			    "Not a valid version %u RTM message - "
-			    "%u bytes version %u\n",
-			    RTM_VERSION, size, p->ifam_version);
-		return;
-	}
-
-	switch (p->ifam_type) {
-	case RTM_NEWADDR:
-	case RTM_DELADDR:
-	case RTM_ADD:
-	case RTM_DELETE:
-		flag = 1;
-		break;
-	default:
-		break;
-	}
-
-	if (debuglevel > 0)
-		(void) fprintf(stderr,
-		    "pfild:handle_msg(): msg rcvd %d flag %d\n",
-		    p->ifam_type, flag);
-}
-
-
-#include <arpa/inet.h>
-static const char *
-dumpaddr(void *p)
-{
-	static char buf[INET6_ADDRSTRLEN];
-	struct sockaddr_in *sin = p;
-	struct sockaddr_in6 *sin6 = p;
-	switch (sin->sin_family) {
-	case AF_INET:
-		return (inet_ntop(sin->sin_family, &sin->sin_addr, buf,
-		    sizeof (buf)));
-	case AF_INET6:
-		return (inet_ntop(sin6->sin6_family, &sin6->sin6_addr, buf,
-		    sizeof (buf)));
-	default:
-		return ("<none>");
-	}
-}
-
-
-#define	ERRBUFSIZE 100
-static char errbuf[ERRBUFSIZE];
-
-#define	LIFN_MARGIN 5		/* a few extra in case things are changing */
-
-/*
- * Fetch the address configuration data for all interfaces and push it into
- * the pfil kernel module.  Fetch the routing table, compute the valid address
- * set data for all interfaces and push it into the pfil kernel module.
- */
-static int
-do_update(void)
-{
-	int numifs, i;
-	struct lifreq *lifrbuf;
-	struct lifconf lifc;
-	struct pfil_ifaddrs *ifaddrlist;
-	struct lifnum lifn;
-	const int lifc_flags = 0;
-	void *buf;
-	size_t bufsize;
-
-	flag = 0;
-
-	lifn.lifn_family = AF_UNSPEC;
-	lifn.lifn_flags = lifc_flags;
-	if (ioctl(ip_fd, SIOCGLIFNUM, (char *)&lifn) < 0) {
-		(void) snprintf(errbuf, ERRBUFSIZE, "SIOCGLIFNUM: %s",
-		    strerror(errno));
-		return (-1);
-	}
-
-	bufsize = (lifn.lifn_count + LIFN_MARGIN) * sizeof (struct lifreq);
-	buf = malloc(bufsize);
-	if (buf == NULL) {
-		(void) snprintf(errbuf, ERRBUFSIZE, "malloc: %s",
-		    strerror(errno));
-		return (-1);
-	}
-	lifrbuf = buf;
-	lifc.lifc_family = AF_UNSPEC;
-	lifc.lifc_flags = lifc_flags;
-	lifc.lifc_buf = buf;
-	lifc.lifc_len = bufsize;
-	if (ioctl(ip_fd, SIOCGLIFCONF, (char *)&lifc) < 0) {
-		(void) snprintf(errbuf, ERRBUFSIZE, "SIOCGLIFCONF: %s",
-		    strerror(errno));
-		free(buf);
-		return (-1);
-	}
-
-	numifs = lifc.lifc_len / sizeof (struct lifreq);
-
-	/* Allocate memory for the number of interfaces retrieved. */
-	ifaddrlist = calloc(numifs, sizeof (struct pfil_ifaddrs));
-	if (ifaddrlist == NULL) {
-		(void) snprintf(errbuf, ERRBUFSIZE, "calloc: %s",
-		    strerror(errno));
-		free(buf);
-		return (-1);
-	}
-
-	/* Populate the interface entries in the ifaddrlist. */
-	for (i = 0; i < numifs; i++) {
-		int isv6 = (lifrbuf[i].lifr_addr.ss_family == AF_INET6);
-		int fd = (isv6 ? icmp6_ip6_fd : ip_fd);
-
-		(void) strncpy(ifaddrlist[i].name, lifrbuf[i].lifr_name,
-		    LIFNAMSIZ);
-		(void) memcpy(&ifaddrlist[i].localaddr, &lifrbuf[i].lifr_addr,
-		    sizeof (ifaddrlist[i].localaddr));
-
-		if (ioctl(fd, SIOCGLIFNETMASK, &lifrbuf[i]) < 0) {
-			(void) snprintf(errbuf, ERRBUFSIZE,
-			    "SIOCGLIFNETMASK %.*s: %s",
-			    LIFNAMSIZ, ifaddrlist[i].name, strerror(errno));
-			free(ifaddrlist);
-			free(buf);
-			return (-1);
-		}
-		(void) memcpy(&ifaddrlist[i].netmask, &lifrbuf[i].lifr_addr,
-		    sizeof (ifaddrlist[i].netmask));
-
-		if (ioctl(fd, SIOCGLIFBRDADDR, &lifrbuf[i]) < 0) {
-			if (errno != EADDRNOTAVAIL) {
-				(void) snprintf(errbuf, ERRBUFSIZE,
-				    "SIOCGLIFBRDADDR %.*s: %s",
-				    LIFNAMSIZ, ifaddrlist[i].name,
-				    strerror(errno));
-				free(ifaddrlist);
-				free(buf);
-				return (-1);
-			}
-		} else {
-			(void) memcpy(&ifaddrlist[i].broadaddr,
-			    &lifrbuf[i].lifr_broadaddr,
-			    sizeof (ifaddrlist[i].broadaddr));
-		}
-
-		if (ioctl(fd, SIOCGLIFDSTADDR, &lifrbuf[i]) < 0) {
-			if (errno != EADDRNOTAVAIL) {
-				(void) snprintf(errbuf, ERRBUFSIZE,
-				    "SIOCGLIFDSTADDR %.*s: %s",
-				    LIFNAMSIZ, ifaddrlist[i].name,
-				    strerror(errno));
-				free(ifaddrlist);
-				free(buf);
-				return (-1);
-			}
-		} else {
-			(void) memcpy(&ifaddrlist[i].dstaddr,
-			    &lifrbuf[i].lifr_dstaddr,
-			    sizeof (ifaddrlist[i].dstaddr));
-		}
-
-		if (ioctl(fd, SIOCGLIFMTU, &lifrbuf[i]) < 0) {
-			(void) snprintf(errbuf, ERRBUFSIZE,
-			    "SIOCGLIFDSTADDR %.*s: %s",
-			    LIFNAMSIZ, ifaddrlist[i].name,
-			    strerror(errno));
-			free(ifaddrlist);
-			free(buf);
-			return (-1);
-		} else {
-			ifaddrlist[i].mtu = lifrbuf[i].lifr_mtu;
-		}
-
-		if (debuglevel > 0) {
-			(void) fprintf(stderr, "%.*s:\n",
-			    LIFNAMSIZ, ifaddrlist[i].name);
-			(void) fprintf(stderr, "	localaddr %s (%d)\n",
-			    dumpaddr(&ifaddrlist[i].localaddr),
-			    ifaddrlist[i].localaddr.in.sin_family);
-			(void) fprintf(stderr, "	netmask %s (%d)\n",
-			    dumpaddr(&ifaddrlist[i].netmask),
-			    ifaddrlist[i].netmask.in.sin_family);
-			(void) fprintf(stderr, "	broadaddr %s (%d)\n",
-			    dumpaddr(&ifaddrlist[i].broadaddr),
-			    ifaddrlist[i].broadaddr.in.sin_family);
-			(void) fprintf(stderr, "	dstaddr %s (%d)\n",
-			    dumpaddr(&ifaddrlist[i].dstaddr),
-			    ifaddrlist[i].dstaddr.in.sin_family);
-			(void) fprintf(stderr, "	mtu %u\n",
-			    ifaddrlist[i].mtu);
-		}
-	}
-
-	free(buf);
-
-	/*
-	 * Now send this table of interfaces and addresses down into
-	 * the pfil kernel module.
-	 */
-	if (pfil_msg(PFILCMD_IFADDRS,
-	    ifaddrlist, i * sizeof (struct pfil_ifaddrs)) < 0) {
-		(void) snprintf(errbuf, ERRBUFSIZE,
-		    "PFILCMD_IFADDRS: %s", strerror(errno));
-		free(ifaddrlist);
-		return (-1);
-	}
-
-	/*
-	 * Next, compute and send the table of valid addresses.
-	 */
-
-	if (vas(ifaddrlist, numifs) < 0) {
-		(void) snprintf(errbuf, ERRBUFSIZE,
-		    "PFILCMD_IFADDRSET: %s", strerror(errno));
-		free(ifaddrlist);
-		return (-1);
-	}
-
-	free(ifaddrlist);
-
-	return (0);
-}
-
-
-/*
- * Send an IPv6 packet out from the system using sendmsg on the raw IP socket
- * through the ancillary data.
- */
-static int
-send_ip6_pkt(const void *pkt, size_t len)
-{
-	const struct ip6_hdr *iph = pkt;
-
-	struct sockaddr_in6 sin6;
-	struct iovec iovec;
-	struct msghdr msghdr;
-	struct cmsghdr *cmsgp;
-	struct in6_pktinfo *pktinfop;
-	unsigned char ancdatabuf[sizeof (*cmsgp) + sizeof (*pktinfop) + 100];
-	size_t ancdatalen;
-	int fd;
-
-	cmsgp = (struct cmsghdr *)ancdatabuf;
-	pktinfop = (struct in6_pktinfo *)CMSG_DATA(cmsgp);
-	cmsgp->cmsg_len = ((char *)(pktinfop + 1) - (char *)cmsgp);
-	cmsgp->cmsg_level = IPPROTO_IPV6;
-	cmsgp->cmsg_type = IPV6_PKTINFO;
-	memcpy(&pktinfop->ipi6_addr, &iph->ip6_src,
-		sizeof (pktinfop->ipi6_addr));
-	pktinfop->ipi6_ifindex = 0;
-	ancdatalen = ((char *)(pktinfop + 1) - (char *)cmsgp);
-
-	sin6.sin6_family = AF_INET6;
-	memcpy(&sin6.sin6_addr, &iph->ip6_dst, sizeof (sin6.sin6_addr));
-	sin6.sin6_port = 0;
-	sin6.sin6_scope_id = 0;
-	sin6.sin6_flowinfo = iph->ip6_flow & IPV6_FLOWINFO_TCLASS;
-
-	iovec.iov_base = (char *)(iph + 1);
-	iovec.iov_len = len - sizeof (*iph);
-	msghdr.msg_name = &sin6;
-	msghdr.msg_namelen = sizeof (sin6);
-	msghdr.msg_iov = &iovec;
-	msghdr.msg_iovlen = 1;
-	msghdr.msg_control = ancdatabuf;
-	msghdr.msg_controllen = ancdatalen;
-	msghdr.msg_flags = 0;
-
-	if (iph->ip6_nxt == IPPROTO_ICMPV6)
-		fd = icmp6_ip6_fd;
-	else if (iph->ip6_nxt == IPPROTO_TCP)
-		fd = tcp_ip6_fd;
-	else {
-		errno = EPROTONOSUPPORT;
-		return (-1);
-	}
-	return (sendmsg(fd, &msghdr, 0));
-}
-
-
-/*
- * Send an arbitrary IP packet out from the system using sendto/sendmsg on the
- * raw IP socket.  Due to the awkwardness of the IPv6 socket API, IPv6 packets
- * are limited to ICMP and TCP; other protocols are dropped.
- */
-static void
-sendpkt(const void *buf, int len)
-{
-	const struct ip *iph = buf;
-	int n;
-
-	if (debuglevel > 0) {
-		fprintf(stderr, "pfild sendpkt %u bytes:\n", len);
-		fprintf(stderr, " %08X %08X %08X %08X\n",
-			((uint32_t *)buf)[0],
-			((uint32_t *)buf)[1],
-			((uint32_t *)buf)[2],
-			((uint32_t *)buf)[3]);
-		fprintf(stderr, " %08X %08X %08X %08X\n",
-			((uint32_t *)buf)[4],
-			((uint32_t *)buf)[5],
-			((uint32_t *)buf)[6],
-			((uint32_t *)buf)[7]);
-		fprintf(stderr, " %08X %08X %08X %08X\n",
-			((uint32_t *)buf)[8],
-			((uint32_t *)buf)[9],
-			((uint32_t *)buf)[10],
-			((uint32_t *)buf)[11]);
-	}
-
-	if (iph->ip_v == 4 && len >= 20) {
-		struct sockaddr_in sin;
-		sin.sin_family = AF_INET;
-		sin.sin_port = 0;
-		sin.sin_addr = iph->ip_dst;
-		n = sendto(ip_fd, buf, len, 0, (void *)&sin, sizeof (sin));
-	} else if (iph->ip_v == 6 && len > 40) {
-		n = send_ip6_pkt(buf, len);
-	} else {
-		n = -1;
-		errno = EINVAL;
-	}
-
-	if (n < 0)
-		perror("pfild: raw socket send");
-}
-
-
-static void usage(const char *prog)
-{
-	fprintf(stderr, "%s: [-d]\n", prog);
-	exit(1);
-}
-
-
-int
-main(int argc, char *argv[])
-{
-	int c, n;
-	const int on = 1;
-	int make_daemon = 1;
-	struct pollfd pollfds[2];
-	union { char bytes[1024]; ifa_msghdr_t msg; } buffer;
-	int pid;
-	struct icmp6_filter  filter;
-
-	while ((c = getopt(argc, argv, "d")) != -1) {
-		switch (c) {
-		case '?' :
-			usage(argv[0]);
-			break;
-		case 'd' :
-			make_daemon = 0;
-			debuglevel++;
-			break;
-		}
-	}
-
-	pfil_fd = open("/dev/pfil", O_RDWR);
-	if (pfil_fd < 0) {
-		perror("pfild: open(/dev/pfil)");
-		return (1);
-	}
-
-	ip_fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
-	if (ip_fd < 0) {
-		perror("pfild: inet socket");
-		return (1);
-	}
-	if (setsockopt(ip_fd, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)) < 0) {
-		perror("pfild: inet socket IP_HDRINCL option");
-		return (1);
-	}
-
-	icmp6_ip6_fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
-	if (icmp6_ip6_fd < 0) {
-		perror("pfild: inet6 ICMP6 socket");
-		return (1);
-	}
-	/*
-	 *  ICMPv6 raw socket by default passes all ICMPv6 message received
-	 *  to the application.  We don't care about them, so simply block them
-	 *  all.
-	 */
-	ICMP6_FILTER_SETBLOCKALL(&filter);
-	if (setsockopt(icmp6_ip6_fd, IPPROTO_ICMPV6, ICMP6_FILTER,
-			&filter, sizeof (filter)) < 0) {
-		perror("pfild: inet6 ICMP6 socket type filtering option");
-		return (1);
-	}
-
-	tcp_ip6_fd = socket(AF_INET6, SOCK_RAW, IPPROTO_TCP);
-	if (tcp_ip6_fd < 0) {
-		perror("pfild: inet6 TCP socket");
-		return (1);
-	}
-
-	route_fd = socket(PF_ROUTE, SOCK_RAW, 0);
-	if (route_fd < 0) {
-		perror("pfild: socket(PF_ROUTE)");
-		return (1);
-	}
-
-	if (make_daemon) {
-		/* Background */
-		if ((pid = fork()) > 0)
-			return (0);
-		if (pid < 0) {
-			(void) fprintf(stderr, "%s: fork() failed %s\n",
-			    argv[0], strerror(errno));
-			return (1);
-			/* NOTREACHED */
-		}
-		(void) setsid();
-		(void) close(0);
-		(void) close(1);
-		(void) close(2);
-		(void) open("/dev/null", O_RDWR);
-		(void) dup(0);
-		(void) dup(0);
-		(void) chdir("/");
-	}
-
-	/*
-	 * Main loop:  Poll for messages from PF_ROUTE socket or pfil stream.
-	 * PF_ROUTE messages may indicate a need to update the kernel module's
-	 * interface data.  pfil messages contain packets to be transmitted.
-	 * Errors in processing don't terminate the program, but errors in
-	 * polling will terminate the program to avoid busy looping.
-	 */
-
-	pollfds[0].fd = route_fd;
-	pollfds[0].events = POLLRDNORM;
-	pollfds[1].fd = pfil_fd;
-	pollfds[1].events = POLLRDNORM;
-
-	while (1) {
-		if (flag) {
-			/* Wait for a moment of quiet, then do the update. */
-			n = poll(pollfds, 1, QUIETTIME);
-			if (n < 1 || !(pollfds[0].revents & POLLRDNORM)) {
-				if (do_update() != 0 && make_daemon == 0)
-					(void) fprintf(stderr, "pfild: %s\n",
-					    errbuf);
-			}
-		}
-
-		if (poll(pollfds, 2, -1) < 0) {
-			perror("pfild: poll()");
-			return (1);
-		}
-
-		/* Check for route_fd message. */
-		if (pollfds[0].revents & POLLRDNORM) {
-			n = read(route_fd, &buffer, sizeof (buffer));
-
-			if (n < 1) {
-				if (n < 0)
-					perror("pfild: read(PF_ROUTE)");
-				else
-					(void) fprintf(stderr,
-					    "pfild: read(PF_ROUTE) EOF\n");
-				return (1);
-			}
-
-			handle_msg(&buffer.msg, n);
-		}
-
-		/* Check for pfil_fd message. */
-		if (pollfds[1].revents & POLLRDNORM) {
-			char pktbuf[IP_MAXPACKET];
-			struct strbuf ctl, data;
-			int flags;
-
-			ctl.maxlen = 0;	/* We don't want any control message. */
-			ctl.buf = pktbuf;
-			data.maxlen = sizeof (pktbuf);
-			data.buf = pktbuf;
-			flags = 0;
-
-			n = getmsg(pfil_fd, &ctl, &data, &flags);
-
-			if (n < 0) {
-				perror("pfild: getmsg(pfil)");
-				return (1);
-			}
-			if (n > 0) {
-				fprintf(stderr,
-				    "pfild: invalid packet from kernel "
-				    "n=%d ctl.len=%u data.len=%u\n",
-				    n, ctl.len, data.len);
-				return (1);
-			}
-
-			sendpkt(data.buf, data.len);
-		}
-	}
-
-	/* NOTREACHED */
-}
--- a/usr/src/cmd/ipf/pfild/vas.c	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1258 +0,0 @@
-/*
- * Copyright (C) 2003 by Darren Reed.
- *
- * See the IPFILTER.LICENCE file for details on licencing.
- *
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/stream.h>
-#include <stropts.h>
-#include <sys/strstat.h>
-#include <sys/sysmacros.h>
-#include <sys/tihdr.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <net/if.h>
-#include <net/route.h>
-#include <inet/common.h>
-#include <inet/mib2.h>
-#include <inet/ip.h>
-#include <inet/ip6.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <fcntl.h>
-#include <sys/systeminfo.h>
-#include <arpa/inet.h>
-#include "pfild.h"
-
-#ifndef MIN
-#define	MIN(a, b)	(((a) < (b)) ? (a) : (b))
-#endif
-
-extern int pfil_msg(uint32_t, void *, size_t);
-
-/*
- * vas.c:  Valid Address Set computation and communication for pfild
- *
- * pfild computes a "valid source address set" for each interface and hands the
- * resulting data to the pfil module which makes it available to pfil clients.
- * The ipf module uses the valid address sets to implement the fr_chksrc
- * feature (automatic protection from source address spoofing).
- *
- * A valid source address for a packet received on given interface is defined
- * as an address which, if used as a destination, would be routed to that
- * interface.  This code assumes that only inbound traffic will be tested
- * against the valid address sets; thus all local and loopback addresses are
- * considered invalid.
- *
- * The TPI MIB interface is used to read the current routing table.  A
- * request (T_SVR4_OPTMGMT_REQ) is sent to /dev/arp and the replies are read,
- * discarding most of them, but saving the two that contain the IPv4 and IPv6
- * routing tables.  Also inspected are two other messages that each happen to
- * contain a constant needed to parse the routing table messages.
- *
- * An address set is represented as a sorted list of mutually discontiguous
- * non-empty inclusive spans.  In the kernel, this list can be efficiently
- * binary-searched.  In user space, we can compute unions and intersections of
- * address sets.  In either case, IPv4 addresses are stored in host byte order
- * for efficient numerical comparisons.  IPv6 addresses will be compared
- * byte-at-a-time so they are kept in conventional struct in6_addr form
- * (network byte order).
- */
-
-
-/*
- * Defining macro used in IPv6 address comparation, add/minus,
- * increase/decrease.
- */
-
-typedef	union	i6addr	{
-	uint32_t	i6[4];
-} i6addr_t;
-
-#define	I60(x)	(((i6addr_t *)(x))->i6[0])
-#define	I61(x)	(((i6addr_t *)(x))->i6[1])
-#define	I62(x)	(((i6addr_t *)(x))->i6[2])
-#define	I63(x)	(((i6addr_t *)(x))->i6[3])
-
-#define	HI60(x)	ntohl(((i6addr_t *)(x))->i6[0])
-#define	HI61(x)	ntohl(((i6addr_t *)(x))->i6[1])
-#define	HI62(x)	ntohl(((i6addr_t *)(x))->i6[2])
-#define	HI63(x)	ntohl(((i6addr_t *)(x))->i6[3])
-
-#define	IP6_EQ(a, b)	(IN6_ARE_ADDR_EQUAL(a, b))
-#define	IP6_GT(a, b)	(HI60(a) > HI60(b) || (HI60(a) == HI60(b) && \
-			(HI61(a) > HI61(b) || (HI61(a) == HI61(b) && \
-			(HI62(a) > HI62(b) || (HI62(a) == HI62(b) && \
-			HI63(a) > HI63(b)))))))
-#define	IP6_LT(a, b)	(HI60(a) < HI60(b) || (HI60(a) == HI60(b) && \
-			(HI61(a) < HI61(b) || (HI61(a) == HI61(b) && \
-			(HI62(a) < HI62(b) || (HI62(a) == HI62(b) && \
-			HI63(a) < HI63(b)))))))
-#define	IP6_GE(a, b)	(IP6_EQ(a, b) || IP6_GT(a, b))
-#define	IP6_LE(a, b)	(IP6_EQ(a, b) || IP6_LT(a, b))
-
-#define	NLADD(n, x)	htonl(ntohl(n) + (x))
-#define	NLMIN(n, x)	htonl(ntohl(n) - (x))
-#define	IP6_INC(a)	\
-		{ i6addr_t *_i6 = (i6addr_t *)(a); \
-		_i6->i6[3] = NLADD(_i6->i6[3], 1); \
-		if (_i6->i6[3] == 0) { \
-			_i6->i6[2] = NLADD(_i6->i6[2], 1); \
-			if (_i6->i6[2] == 0) { \
-				_i6->i6[1] = NLADD(_i6->i6[1], 1); \
-				if (_i6->i6[1] == 0) { \
-					_i6->i6[0] = NLADD(_i6->i6[0], 1); \
-				} \
-			} \
-		} \
-		}
-#define	IP6_DEC(a)	\
-		{ i6addr_t *_i6 = (i6addr_t *)(a); \
-		_i6->i6[3] = NLMIN(_i6->i6[3], 1); \
-		if (_i6->i6[3] == 0xFFFFFFFFU) { \
-			_i6->i6[2] = NLMIN(_i6->i6[2], 1); \
-			if (_i6->i6[2] == 0xFFFFFFFFU) { \
-				_i6->i6[1] = NLMIN(_i6->i6[1], 1); \
-				if (_i6->i6[1] == 0xFFFFFFFFU) { \
-					_i6->i6[0] = NLMIN(_i6->i6[0], 1); \
-				} \
-			} \
-		} \
-		}
-
-#define	IP6_FIRST(a, m)	\
-		{ if ((m) > 96) { \
-			I63(a) = ntohl(I63(a)); \
-			I63(a) &= (0xFFFFFFFF << (128 - (m))); \
-			I63(a) = htonl(I63(a)); \
-		} else if ((m) > 64) { \
-			I62(a) = ntohl(I62(a)); \
-			I62(a) &= (0xFFFFFFFF << (96 - (m))); \
-			I62(a) = htonl(I62(a)); \
-			I63(a) = 0; \
-		} else if ((m) > 32) { \
-			I61(a) = ntohl(I61(a)); \
-			I61(a) &= (0xFFFFFFFF << (64 - (m))); \
-			I61(a) = htonl(I61(a)); \
-			I62(a) = 0; \
-			I63(a) = 0; \
-		} else if ((m) > 0) { \
-			I60(a) = ntohl(I60(a)); \
-			I60(a) &= (0xFFFFFFFF << (32 - (m))); \
-			I60(a) = htonl(I60(a)); \
-			I61(a) = 0; \
-			I62(a) = 0; \
-			I63(a) = 0; \
-		} else { \
-			I60(a) = 0; \
-			I61(a) = 0; \
-			I62(a) = 0; \
-			I63(a) = 0; \
-		} \
-		}
-#define	IP6_LAST(a, m) \
-		{ if ((m) == 128) { \
-		} else if ((m) >= 96) { \
-			I63(a) = ntohl(I63(a)); \
-			I63(a) |= (0xFFFFFFFF >> ((m) - 96)); \
-			I63(a) = htonl(I63(a)); \
-		} else if ((m) >= 64) { \
-			I62(a) = ntohl(I62(a)); \
-			I62(a) |= (0xFFFFFFFF >> ((m) - 64)); \
-			I62(a) = htonl(I62(a)); \
-			I63(a) = 0xFFFFFFFFU; \
-		} else if ((m) >= 32) { \
-			I61(a) = ntohl(I61(a)); \
-			I61(a) |= (0xFFFFFFFF >> ((m) - 32)); \
-			I61(a) = htonl(I61(a)); \
-			I62(a) = 0xFFFFFFFFU; \
-			I63(a) = 0xFFFFFFFFU; \
-		} else if ((m) >= 0) { \
-			I60(a) = ntohl(I60(a)); \
-			I60(a) |= (0xFFFFFFFF >>  (m)); \
-			I60(a) = htonl(I60(a)); \
-			I61(a) = 0xFFFFFFFFU; \
-			I62(a) = 0xFFFFFFFFU; \
-			I63(a) = 0xFFFFFFFFU; \
-		} \
-		}
-
-
-/*
- * User space uses a linked list of spans, rather than the array that is
- * used in the kernel and in the /dev/pfil messages.
- */
-
-struct spannode {
-	struct spannode *next;
-	union {
-		struct pfil_v4span v4;
-		struct pfil_v6span v6;
-	} span;
-};
-
-struct addrset {
-	const char *name;
-	uint8_t af;
-	struct spannode *head;
-};
-
-/*
- * Allocate and initialize a new struct addrset.
- * Returns pointer to new instance or NULL for allocation failure.
- */
-static struct addrset *
-new_addrset(const char *name, uint8_t af)
-{
-	struct addrset *asp = malloc(sizeof (*asp));
-
-	if (asp == NULL)
-		return (NULL);
-
-	asp->name = name;
-	asp->af = af;
-	asp->head = NULL;
-
-	return (asp);
-}
-
-/*
- * Free an addrset instance.
- */
-static void
-delete_addrset(struct addrset *asp)
-{
-	struct spannode *tmp;
-	while (asp->head != NULL) {
-		tmp = asp->head->next;
-		free(asp->head);
-		asp->head = tmp;
-	}
-	free(asp);
-}
-
-/*
- * Add a single IPv4 address or a prefix to a set.
- * Returns 0 for success, non-zero for failure (allocation error).
- * addr and mask are passed in network byte order, but immediately converted
- * to host byte order for comparisons.
- */
-static int
-addrset_add_v4(struct addrset *asp, ipaddr_t addr, ipaddr_t mask)
-{
-	struct spannode **ptpn, *p;
-	uint32_t first, last;		/* host byte order */
-
-	assert(asp->af == AF_INET);
-
-	first = ntohl(addr & mask);
-	last = ntohl(addr | ~mask);
-
-	/*
-	 * Search through the list linearly, looking for either:  an entry
-	 * contiguous to the one being added (with which we will merge) or a
-	 * discontiguous entry with a higher address (before which we will
-	 * insert).  If no match, we will append at the end.
-	 */
-	for (ptpn = &asp->head; (p = *ptpn) != NULL; ptpn = &p->next) {
-		if (first > 0 && first-1 > p->span.v4.last)
-			continue;
-		if (last == 0xFFFFFFFF || last+1 >= p->span.v4.first) {
-			/* Merge with this entry. */
-			if (first < p->span.v4.first)
-				p->span.v4.first = first;
-			while (last > p->span.v4.last) {
-				struct spannode *next = p->next;
-
-				if (next != NULL &&
-				    last >= next->span.v4.first - 1) {
-					/* Merge this span with the next. */
-					p->span.v4.last = next->span.v4.last;
-					p->next = next->next;
-					free(next);
-				} else {
-					p->span.v4.last = last;
-				}
-			}
-			return (0);
-		} else {
-			/* Found the insertion point; exit the loop. */
-			break;
-		}
-	}
-
-	/* ptpn now points to the "previous next" where we need to insert. */
-
-	p = malloc(sizeof (*p));
-	if (p == NULL)
-		return (1);
-	p->span.v4.first = first;
-	p->span.v4.last = last;
-	p->next = *ptpn;
-	*ptpn = p;
-
-	return (0);
-}
-
-/*
- * Remove one range of IPv4 addresses from a set.
- */
-static int
-addrset_delete_v4(struct addrset *asp, uint32_t first, uint32_t last)
-{
-	struct spannode **ptpn, *p;
-
-	/*
-	 * Search through the list linearly, looking for any of:  an entry
-	 * entirely contained with the range being deleted (which we will
-	 * delete from the list) or an entry overlapping the first address of
-	 * the range (which we will truncate at its end) or an entry
-	 * overlapping the last address of the range (which we will truncate at
-	 * its beginning) or an entry which entirely contains the range being
-	 * deleted plus at least one address beyond in each direction (which we
-	 * will split into two entries) or an entry with a higher address than
-	 * we are deleting (at which point we are done).
-	 */
-	for (ptpn = &asp->head; (p = *ptpn) != NULL; ptpn = &p->next) {
-		if (p->span.v4.first > last)
-			return (0);		/* all done */
-		if (p->span.v4.last < first)
-			continue;	/* keep searching */
-		while (p->span.v4.first >= first &&
-		    p->span.v4.last <= last) {
-			/* Delete a span entirely. */
-			*ptpn = p->next;
-			free(p);
-			p = *ptpn;
-			if (p == NULL || p->span.v4.first > last)
-				return (0);	/* all done */
-		}
-		if (p->span.v4.first >= first) {
-			/* Truncate a span at its beginning. */
-			p->span.v4.first = last + 1;
-		} else if (p->span.v4.last <= last) {
-			/* Truncate a span at its end. */
-			p->span.v4.last = first - 1;
-		} else {
-			/* Split a span into two. */
-			struct spannode *p2 = malloc(sizeof (*p2));
-			if (p2 == NULL)
-				return (1);
-			p2->span.v4.first = last + 1;
-			p2->span.v4.last = p->span.v4.last;
-			p2->next = p->next;
-			p->span.v4.last = first - 1;
-			p->next = p2;
-		}
-	}
-
-	return (0);
-}
-
-/*
- * Add a single IPv6 address or a prefix to a set.
- * Returns 0 for success, non-zero for failure (allocation error).
- * addr is passed in network byte order, but keep this order.
- * prefixlen is the prefix length.
- */
-static int
-addrset_add_v6(struct addrset *asp, in6_addr_t addr, int prefixlen)
-{
-	struct spannode **ptpn, *p;
-	in6_addr_t first, last, temp;
-	const in6_addr_t ipv6_all_zeros = IN6ADDR_ANY_INIT;
-	const in6_addr_t ipv6_all_ones = { 	0xff, 0xff, 0xff, 0xff,
-						0xff, 0xff, 0xff, 0xff,
-						0xff, 0xff, 0xff, 0xff,
-						0xff, 0xff, 0xff, 0xff };
-
-	assert(asp->af == AF_INET6);
-	assert((prefixlen >= 0) && (prefixlen <= 128));
-
-	first = addr;
-	last = addr;
-	IP6_FIRST(&first, prefixlen);
-	IP6_LAST(&last, prefixlen);
-
-	/*
-	 * Search through the list linearly, looking for either:  an entry
-	 * contiguous to the one being added (with which we will merge) or a
-	 * discontiguous entry with a higher address (before which we will
-	 * insert).  If no match, we will append at the end.
-	 */
-	for (ptpn = &asp->head; (p = *ptpn) != NULL; ptpn = &p->next) {
-		temp = first;
-		IP6_DEC(&temp);
-		if (IP6_GT(&first, &ipv6_all_zeros) &&
-		    IP6_GT(&temp, &p->span.v6.last))
-			continue;
-		temp = last;
-		IP6_INC(&temp);
-		if (IP6_EQ(&last, &ipv6_all_ones) ||
-		    IP6_GE(&temp, &p->span.v6.first)) {
-			/* Merge with this entry. */
-			if (IP6_LT(&first, &p->span.v6.first))
-				p->span.v6.first = first;
-			while (IP6_GT(&last, &p->span.v6.last)) {
-				struct spannode *next = p->next;
-
-				if (next == NULL) {
-					p->span.v6.last = last;
-					break;
-				}
-
-				temp = next->span.v6.first;
-				IP6_DEC(&temp);
-				if (IP6_GE(&last, &temp)) {
-					/* Merge this span with the next. */
-					p->span.v6.last = next->span.v6.last;
-					p->next = next->next;
-					free(next);
-				} else {
-					p->span.v6.last = last;
-				}
-			}
-			return (0);
-		} else {
-			/* Found the insertion point; exit the loop. */
-			break;
-		}
-	}
-
-	/* ptpn now points to the "previous next" where we need to insert. */
-
-	p = malloc(sizeof (*p));
-	if (p == NULL)
-		return (1);
-	p->span.v6.first = first;
-	p->span.v6.last = last;
-	p->next = *ptpn;
-	*ptpn = p;
-
-	return (0);
-}
-
-/*
- * Remove one range of IPv6 addresses from a set.
- */
-static int
-addrset_delete_v6(struct addrset *asp, in6_addr_t first, in6_addr_t last)
-{
-	struct spannode **ptpn, *p;
-	in6_addr_t temp;
-
-	/*
-	 * Search through the list linearly, looking for any of:  an entry
-	 * entirely contained with the range being deleted (which we will
-	 * delete from the list) or an entry overlapping the first address of
-	 * the range (which we will truncate at its end) or an entry
-	 * overlapping the last address of the range (which we will truncate at
-	 * its beginning) or an entry which entirely contains the range being
-	 * deleted plus at least one address beyond in each direction (which we
-	 * will split into two entries) or an entry with a higher address than
-	 * we are deleting (at which point we are done).
-	 */
-	for (ptpn = &asp->head; (p = *ptpn) != NULL; ptpn = &p->next) {
-		if (IP6_GT(&p->span.v6.first, &last))
-			return (0);		/* all done */
-		if (IP6_LT(&p->span.v6.last, &first))
-			continue;	/* keep searching */
-		while (IP6_GE(&p->span.v6.first, &first) &&
-		    IP6_LE(&p->span.v6.last, &last)) {
-			/* Delete a span entirely. */
-			*ptpn = p->next;
-			free(p);
-			p = *ptpn;
-			if (p == NULL || IP6_GT(&p->span.v6.first, &last))
-				return (0);	/* all done */
-		}
-		if (IP6_GE(&p->span.v6.first, &first)) {
-			/* Truncate a span at its beginning. */
-			temp = last;
-			IP6_INC(&temp);
-			p->span.v6.first = temp;
-		} else if (IP6_LE(&p->span.v6.last, &last)) {
-			/* Truncate a span at its end. */
-			temp = first;
-			IP6_DEC(&temp);
-			p->span.v6.last = temp;
-		} else {
-			/* Split a span into two. */
-			struct spannode *p2 = malloc(sizeof (*p2));
-			if (p2 == NULL)
-				return (1);
-			temp = last;
-			IP6_INC(&temp);
-			p2->span.v6.first = temp;
-			p2->span.v6.last = p->span.v6.last;
-			p2->next = p->next;
-			temp = first;
-			IP6_DEC(&temp);
-			p->span.v6.last = temp;
-			p->next = p2;
-		}
-	}
-
-	return (0);
-}
-
-/*
- * Compute the set difference (remove elements in set 2 from set 1).
- */
-static void
-addrset_diff(struct addrset *asp1, struct addrset *asp2)
-{
-	struct spannode *p;
-
-	if (asp1->af != asp2->af)
-		return;
-
-	/* For each span in set 2, delete it from set 1. */
-	if (asp1->af == AF_INET)
-		for (p = asp2->head; p; p = p->next)
-			(void) addrset_delete_v4(asp1,
-			    p->span.v4.first, p->span.v4.last);
-	else if (asp1->af == AF_INET6)
-		for (p = asp2->head; p; p = p->next)
-			(void) addrset_delete_v6(asp1,
-			    p->span.v6.first, p->span.v6.last);
-}
-
-
-typedef struct mib_item_s {
-	int			group;
-	int			mib_id;
-	void			*valp;
-	size_t			length;
-} mib_item_t;
-
-static void	mibload(int sd);
-static void	mibfree(mib_item_t *item);
-static void	mib_get_constants(mib_item_t *item);
-
-static int ipRouteEntrySize;
-static int ipv6RouteEntrySize;
-
-static mib_item_t *ipv4Table;
-static mib_item_t *ipv6Table;
-
-/*
- * Copy and NUL-terminate a MIB octet-string.
- */
-static void
-octetstr(Octet_t *op, char *dst, uint_t dstlen)
-{
-	size_t n = MIN(dstlen - 1, op->o_length);
-	memcpy(dst, op->o_bytes, n);
-	dst[n] = '\0';
-}
-
-/*
- * Read the whole IP MIB, looking for the routing related entries.
- * Save the IPv4 and IPv6 route table items and peek into a couple other
- * items to learn the increments between records in the route table items.
- */
-static void
-mibload(int sd)
-{
-	/*
-	 * buf is an automatic for this function, so the
-	 * compiler has complete control over its alignment;
-	 * it is assumed this alignment is satisfactory for
-	 * it to be casted to certain other struct pointers
-	 * here, such as struct T_optmgmt_ack * .
-	 */
-	uintptr_t		buf[512 / sizeof (uintptr_t)];
-	int			flags;
-	int			j, getcode;
-	struct strbuf		ctlbuf, databuf;
-	struct T_optmgmt_req	*tor = (struct T_optmgmt_req *)buf;
-	struct T_optmgmt_ack	*toa = (struct T_optmgmt_ack *)buf;
-	struct T_error_ack	*tea = (struct T_error_ack *)buf;
-	struct opthdr		*req;
-	mib_item_t		*temp;
-
-	ipv4Table = NULL;
-	ipv6Table = NULL;
-
-	tor->PRIM_type = T_SVR4_OPTMGMT_REQ;
-	tor->OPT_offset = sizeof (struct T_optmgmt_req);
-	tor->OPT_length = sizeof (struct opthdr);
-	tor->MGMT_flags = T_CURRENT;
-	req = (struct opthdr *)&tor[1];
-	req->level = MIB2_IP;		/* any MIB2_xxx value ok here */
-	req->name  = 0;
-	req->len   = 0;
-
-	ctlbuf.buf = (char *)buf;
-	ctlbuf.len = tor->OPT_length + tor->OPT_offset;
-	flags = 0;
-	if (putmsg(sd, &ctlbuf, (struct strbuf *)0, flags) == -1) {
-		perror("mibget: putmsg(ctl) failed");
-		goto error_exit;
-	}
-
-	/*
-	 * Each reply consists of a ctl part for one fixed structure
-	 * or table, as defined in mib2.h.  The format is a T_OPTMGMT_ACK,
-	 * containing an opthdr structure.  level/name identify the entry,
-	 * len is the size of the data part of the message.
-	 */
-	req = (struct opthdr *)&toa[1];
-	ctlbuf.maxlen = sizeof (buf);
-	j = 1;
-	for (;;) {
-		flags = 0;
-		getcode = getmsg(sd, &ctlbuf, (struct strbuf *)0, &flags);
-		if (getcode == -1) {
-			perror("mibget getmsg(ctl) failed");
-			goto error_exit;
-		}
-		if (getcode == 0 &&
-		    ctlbuf.len >= sizeof (struct T_optmgmt_ack) &&
-		    toa->PRIM_type == T_OPTMGMT_ACK &&
-		    toa->MGMT_flags == T_SUCCESS &&
-		    req->len == 0)
-			return;
-
-		if (ctlbuf.len >= sizeof (struct T_error_ack) &&
-		    tea->PRIM_type == T_ERROR_ACK) {
-			(void) fprintf(stderr,
-			    "mibget %d gives T_ERROR_ACK: TLI_error = 0x%lx, "
-			    "UNIX_error = 0x%lx\n",
-			    j, tea->TLI_error, tea->UNIX_error);
-
-			errno = (tea->TLI_error == TSYSERR) ?
-			    tea->UNIX_error : EPROTO;
-			goto error_exit;
-		}
-
-		if (getcode != MOREDATA ||
-		    ctlbuf.len < sizeof (struct T_optmgmt_ack) ||
-		    toa->PRIM_type != T_OPTMGMT_ACK ||
-		    toa->MGMT_flags != T_SUCCESS) {
-			(void) printf("mibget getmsg(ctl) %d returned %d, "
-			    "ctlbuf.len = %d, PRIM_type = %ld\n",
-			    j, getcode, ctlbuf.len, toa->PRIM_type);
-
-			if (toa->PRIM_type == T_OPTMGMT_ACK)
-				(void) printf("T_OPTMGMT_ACK: "
-				    "MGMT_flags = 0x%lx, req->len = %ld\n",
-				    toa->MGMT_flags, req->len);
-			errno = ENOMSG;
-			goto error_exit;
-		}
-
-		temp = malloc(sizeof (mib_item_t));
-		if (temp == NULL) {
-			perror("mibget malloc failed");
-			goto error_exit;
-		}
-		temp->group = req->level;
-		temp->mib_id = req->name;
-		temp->length = req->len;
-		temp->valp = malloc(req->len);
-		if (temp->valp == NULL) {
-			free(temp);
-			goto error_exit;
-		}
-
-		databuf.maxlen = temp->length;
-		databuf.buf    = temp->valp;
-		databuf.len    = 0;
-		flags = 0;
-		getcode = getmsg(sd, (struct strbuf *)0, &databuf, &flags);
-		if (getcode == -1) {
-			perror("mibload getmsg(data) failed");
-			mibfree(temp);
-			goto error_exit;
-		} else if (getcode != 0) {
-			(void) printf("mibload getmsg(data) returned %d, "
-			    "databuf.maxlen = %d, databuf.len = %d\n",
-			    getcode, databuf.maxlen, databuf.len);
-			mibfree(temp);
-			goto error_exit;
-		}
-
-		j++;
-
-		if (temp->group != MIB2_IP &&
-		    temp->group != MIB2_IP6) {
-			mibfree(temp);
-			continue;
-		}
-
-		switch (temp->mib_id) {
-		case MIB2_IP_ROUTE:
-			if (ipv4Table)
-				mibfree(ipv4Table);
-			ipv4Table = temp;
-			break;
-		case MIB2_IP6_ROUTE:
-			if (ipv6Table)
-				mibfree(ipv6Table);
-			ipv6Table = temp;
-			break;
-		case 0:
-			mib_get_constants(temp);
-			/* FALLTHROUGH */
-		default:
-			mibfree(temp);
-			break;
-		}
-	}
-	/* NOTREACHED */
-
-error_exit:;
-}
-
-/*
- * mibfree: frees a (mib_item_t *) loaded by mibload()
- */
-static void
-mibfree(mib_item_t *item)
-{
-	if (item->valp != NULL)
-		free(item->valp);
-	free(item);
-}
-
-#define	IPROUTEENTRYALIGNMENT 4
-#define	IP6ROUTEENTRYALIGNMENT 4
-
-/* Extract constant sizes. */
-static void
-mib_get_constants(mib_item_t *item)
-{
-	switch (item->group) {
-	case MIB2_IP: {
-		mib2_ip_t *ip = item->valp;
-
-		ipRouteEntrySize = ip->ipRouteEntrySize;
-		assert(IS_P2ALIGNED(ipRouteEntrySize, IPROUTEENTRYALIGNMENT));
-		break;
-	}
-	case MIB2_IP6: {
-		mib2_ipv6IfStatsEntry_t *ip6 = item->valp;
-		/* Just use the first entry */
-
-		ipv6RouteEntrySize = ip6->ipv6RouteEntrySize;
-		assert(IS_P2ALIGNED(ipv6RouteEntrySize,
-		    IP6ROUTEENTRYALIGNMENT));
-		break;
-	}
-	}
-}
-
-
-/*
- * Compose a PFILCMD_IFADDRSET message for each interface and deliver them to
- * pfil.  Returns 0 for success, non-zero for failure.
- */
-static int
-pfil_ifaddrset_msg(struct addrset **ifs, int numifs)
-{
-	int status = 0, i;
-	struct pfil_ifaddrset *ifaddrset = NULL;
-
-	for (i = 0; i < numifs; i++)
-		if (ifs[i]->af == AF_INET) {
-			struct spannode *p1;
-			struct pfil_v4span *p2;
-			int nspans = 0;
-			size_t size;
-
-			for (p1 = ifs[i]->head; p1; p1 = p1->next)
-				nspans++;
-			size = sizeof (struct pfil_ifaddrset) +
-			    nspans * sizeof (struct pfil_v4span);
-			ifaddrset = realloc(ifaddrset, size);
-			if (ifaddrset == NULL)
-				return (-1);
-
-			(void) strlcpy(ifaddrset->name, ifs[i]->name,
-			    LIFNAMSIZ);
-			ifaddrset->af = ifs[i]->af;
-			ifaddrset->nspans = nspans;
-			p2 = (struct pfil_v4span *)(ifaddrset + 1);
-			for (p1 = ifs[i]->head; p1; p1 = p1->next) {
-				p2->first = p1->span.v4.first;
-				p2->last = p1->span.v4.last;
-				++p2;
-			}
-
-			status = pfil_msg(PFILCMD_IFADDRSET, ifaddrset, size);
-			if (status != 0)
-				break;
-		} else if (ifs[i]->af == AF_INET6) {
-			struct spannode *p1;
-			struct pfil_v6span *p2;
-			int nspans = 0;
-			size_t size;
-
-			for (p1 = ifs[i]->head; p1; p1 = p1->next)
-				nspans++;
-			size = sizeof (struct pfil_ifaddrset) +
-			    nspans * sizeof (struct pfil_v6span);
-			ifaddrset = realloc(ifaddrset, size);
-			if (ifaddrset == NULL)
-				return (-1);
-
-			(void) strlcpy(ifaddrset->name, ifs[i]->name,
-			    LIFNAMSIZ);
-			ifaddrset->af = ifs[i]->af;
-			ifaddrset->nspans = nspans;
-			p2 = (struct pfil_v6span *)(ifaddrset + 1);
-			for (p1 = ifs[i]->head; p1; p1 = p1->next) {
-				p2->first = p1->span.v6.first;
-				p2->last = p1->span.v6.last;
-				++p2;
-			}
-
-			status = pfil_msg(PFILCMD_IFADDRSET, ifaddrset, size);
-			if (status != 0)
-				break;
-		}
-
-	if (ifaddrset != NULL)
-		free(ifaddrset);
-
-	return (status);
-}
-
-/*
- * Find an interface through which the gateway is reachable and return its
- * name in the specififed buffer.
- */
-static void
-findgwif_v4(in_addr_t gw, char outif[], size_t size)
-{
-	mib2_ipRouteEntry_t *rp;
-
-	for (rp = ipv4Table->valp;
-	    (char *)rp < (char *)ipv4Table->valp + ipv4Table->length;
-	    rp = (mib2_ipRouteEntry_t *)
-	    ((char *)rp + ipRouteEntrySize)) {
-		if ((rp->ipRouteInfo.re_ire_type & IRE_INTERFACE) &&
-		    (rp->ipRouteIfIndex.o_length > 0) &&
-		    ((gw & rp->ipRouteMask) == rp->ipRouteDest)) {
-			octetstr(&rp->ipRouteIfIndex,
-			    outif, size);
-			return;
-		}
-	}
-	outif[0] = '\0';
-}
-
-/*
- * Find an interface through which the gateway is reachable and return its
- * name in the specififed buffer.
- */
-static void
-findgwif_v6(in6_addr_t gw, char outif[], size_t size)
-{
-	mib2_ipv6RouteEntry_t *rp;
-	in6_addr_t temp;
-
-	for (rp = ipv6Table->valp;
-	    (char *)rp < (char *)ipv6Table->valp + ipv6Table->length;
-	    rp = (mib2_ipv6RouteEntry_t *)
-	    ((char *)rp + ipv6RouteEntrySize)) {
-		temp = gw;
-		IP6_FIRST(&temp, rp->ipv6RoutePfxLength);
-		if ((rp->ipv6RouteInfo.re_ire_type & IRE_INTERFACE) &&
-		    (rp->ipv6RouteIfIndex.o_length > 0) &&
-		    (IP6_EQ(&temp, &rp->ipv6RouteDest))) {
-			octetstr(&rp->ipv6RouteIfIndex,
-			    outif, size);
-			return;
-		}
-	}
-	outif[0] = '\0';
-}
-
-/*
- * Compute the valid address sets for the specified interfaces, then compose a
- * series of PFILCMD_IFADDRSET messages and deliver them to pfil.  Returns 0 for
- * success, non-zero for failure.
- */
-int
-vas(const struct pfil_ifaddrs *ifaddrlist, int numifs)
-{
-	const in6_addr_t ipv6_unspecified = IN6ADDR_ANY_INIT;
-	const in6_addr_t ipv6_loopback_addr = IN6ADDR_LOOPBACK_INIT;
-	const in6_addr_t ipv6_multi_addr = { 	0xffU, 0x00U, 0, 0,
-						0, 0, 0, 0,
-						0, 0, 0, 0,
-						0, 0, 0, 0 };
-
-	struct addrset **ifs = NULL, *illegal_v4 = NULL, *illegal_v6 = NULL;
-	int sd, i, status;
-
-	sd = open("/dev/arp", O_RDWR);
-	if (sd == -1)
-		return (-1);
-	mibload(sd);
-	(void) close(sd);
-
-	ifs = calloc(numifs, sizeof (*ifs));
-	if (ifs == NULL)
-		goto err;
-	for (i = 0; i < numifs; i++) {
-		/*
-		 * in.sin_family works for in6.sin6_family too.
-		 * Both are located in the same address.
-		 */
-		ifs[i] = new_addrset(ifaddrlist[i].name,
-		    ifaddrlist[i].localaddr.in.sin_family);
-		if (ifs[i] == NULL)
-			goto err;
-	}
-
-	illegal_v4 = new_addrset("[illegal]", AF_INET);
-	if (illegal_v4 == NULL)
-		goto err;
-
-	/* Multicast addresses are always illegal as source address. */
-	if (addrset_add_v4(illegal_v4,
-	    htonl(INADDR_UNSPEC_GROUP), htonl(IN_CLASSD_NET)))
-		goto err;
-
-	/* Loopback addresses are illegal on non-loopback interfaces. */
-	if (addrset_add_v4(illegal_v4,
-	    htonl(INADDR_LOOPBACK), htonl(IN_CLASSA_NET)))
-		goto err;
-
-	illegal_v6 = new_addrset("[illegal]", AF_INET6);
-	if (illegal_v6 == NULL)
-		goto err;
-
-	/* Multicast addresses are always illegal as source address. */
-	if (addrset_add_v6(illegal_v6, ipv6_multi_addr, 8))
-		goto err;
-
-	/* Loopback addresses are illegal on non-loopback interfaces. */
-	if (addrset_add_v6(illegal_v6, ipv6_loopback_addr, 128))
-		goto err;
-
-	/* Unspecified addresses are always illegal as source address. */
-	if (addrset_add_v6(illegal_v6, ipv6_unspecified, 128))
-		goto err;
-
-	if (ipRouteEntrySize < sizeof (mib2_ipRouteEntry_t) ||
-	    ipv6RouteEntrySize < sizeof (mib2_ipv6RouteEntry_t) ||
-	    (!ipv4Table && !ipv6Table)) {
-		errno = ENOENT;
-err:
-		status = -1;
-		goto done;
-	}
-
-	if (ipv4Table != NULL) {
-		mib2_ipRouteEntry_t *rp;
-
-		for (rp = ipv4Table->valp;
-		    (char *)rp < (char *)ipv4Table->valp + ipv4Table->length;
-		    rp = (mib2_ipRouteEntry_t *)
-		    ((char *)rp + ipRouteEntrySize)) {
-			struct addrset *asp = NULL;
-			char outif[LIFNAMSIZ + 1];
-
-			switch (rp->ipRouteInfo.re_ire_type) {
-			case IRE_CACHE:
-				continue;
-			case IRE_BROADCAST:
-			case IRE_LOCAL:
-				asp = illegal_v4;
-				break;
-			default:
-				if (rp->ipRouteIfIndex.o_length > 0) {
-					octetstr(&rp->ipRouteIfIndex,
-					    outif, sizeof (outif));
-				} else {
-					findgwif_v4(rp->ipRouteNextHop,
-					    outif, sizeof (outif));
-				}
-				if (outif[0] != '\0') {
-					for (i = 0; i < numifs; i++) {
-						if (ifs[i]->af == AF_INET &&
-						    strncmp(outif, ifs[i]->name,
-						    LIFNAMSIZ) == 0) {
-							asp = ifs[i];
-							break;
-						}
-					}
-				}
-				break;
-			}
-			if (asp != NULL &&
-			    addrset_add_v4(asp,
-			    rp->ipRouteDest, rp->ipRouteMask) != 0)
-				goto err;
-		}
-	}
-
-	if (ipv6Table != NULL) {
-		mib2_ipv6RouteEntry_t *rp;
-
-		for (rp = ipv6Table->valp;
-		    (char *)rp < (char *)ipv6Table->valp + ipv6Table->length;
-		    rp = (mib2_ipv6RouteEntry_t *)
-		    ((char *)rp + ipv6RouteEntrySize)) {
-			struct addrset *asp = NULL;
-			char outif[LIFNAMSIZ + 1];
-
-			switch (rp->ipv6RouteInfo.re_ire_type) {
-			case IRE_CACHE:
-				continue;
-			case IRE_BROADCAST:
-			case IRE_LOCAL:
-				asp = illegal_v6;
-				break;
-			default:
-				if (rp->ipv6RouteIfIndex.o_length > 0) {
-					octetstr(&rp->ipv6RouteIfIndex,
-					    outif, sizeof (outif));
-				} else {
-					findgwif_v6(rp->ipv6RouteNextHop,
-					    outif, sizeof (outif));
-				}
-				if (outif[0] != '\0') {
-					for (i = 0; i < numifs; i++) {
-						if (ifs[i]->af == AF_INET6 &&
-						    strncmp(outif, ifs[i]->name,
-						    LIFNAMSIZ) == 0) {
-							asp = ifs[i];
-							break;
-						}
-					}
-				}
-				break;
-			}
-			if (asp != NULL &&
-			    addrset_add_v6(asp, rp->ipv6RouteDest,
-			    rp->ipv6RoutePfxLength) != 0)
-				goto err;
-		}
-	}
-
-	for (i = 0; i < numifs; i++) {
-		if (ifs[i]->af == AF_INET)
-			addrset_diff(ifs[i], illegal_v4);
-		else if (ifs[i]->af == AF_INET6)
-			addrset_diff(ifs[i], illegal_v6);
-	}
-
-	status = pfil_ifaddrset_msg(ifs, numifs);
-#ifdef DEBUG
-	pfil_ifaddrset_msg(&illegal_v4, 1);
-	pfil_ifaddrset_msg(&illegal_v6, 1);
-#endif
-
-done:
-	if (ipv4Table != NULL)
-		mibfree(ipv4Table);
-	if (ipv6Table != NULL)
-		mibfree(ipv6Table);
-
-	for (i = 0; i < numifs; i++)
-		if (ifs[i] != NULL)
-			delete_addrset(ifs[i]);
-	free(ifs);
-	if (illegal_v4 != NULL)
-		delete_addrset(illegal_v4);
-	if (illegal_v6 != NULL)
-		delete_addrset(illegal_v6);
-
-	return (status);
-}
-
-#ifdef DEBUG
-static void
-fatal(int errcode, char *format, ...)
-{
-	va_list argp;
-
-	if (format == NULL)
-		return;
-
-	va_start(argp, format);
-	(void) vfprintf(stderr, format, argp);
-	va_end(argp);
-
-	exit(errcode);
-}
-
-static void
-pr_span(uint8_t af, const struct spannode *p, char *buf, size_t size)
-{
-	char buf1[INET6_ADDRSTRLEN], buf2[INET6_ADDRSTRLEN];
-
-	if (af == AF_INET) {
-		ipaddr_t addr;
-
-		addr = htonl(p->span.v4.first);
-		(void) inet_ntop(AF_INET, &addr, buf1, sizeof (buf1));
-
-		if (p->span.v4.first == p->span.v4.last) {
-			(void) strncpy(buf, buf1, size);
-		} else {
-			addr = htonl(p->span.v4.last);
-			(void) inet_ntop(AF_INET, &addr, buf2, sizeof (buf2));
-			(void) snprintf(buf, size, "%s - %s", buf1, buf2);
-		}
-	} else if (af == AF_INET6) {
-		in6_addr_t addr6;
-
-		addr6 = p->span.v6.first;
-		(void) inet_ntop(AF_INET6, &addr6, buf1, sizeof (buf1));
-
-		if (IP6_EQ(&p->span.v6.first, &p->span.v6.last)) {
-			(void) strncpy(buf, buf1, size);
-		} else {
-			addr6 = p->span.v6.last;
-			(void) inet_ntop(AF_INET6, &addr6, buf2, sizeof (buf2));
-			(void) snprintf(buf, size, "%s - %s", buf1, buf2);
-		}
-	}
-}
-
-static void
-pr_addrset(const struct addrset *asp)
-{
-	struct spannode *p;
-
-	(void) printf("addrset %s (%u):\n", asp->name, asp->af);
-
-	if (asp->head == 0) {
-		(void) puts(" [empty]");
-		return;
-	}
-
-	p = asp->head;
-	while (p != NULL) {
-		char buf[100];
-
-		(void) putchar(' ');
-		pr_span(asp->af, p, buf, sizeof (buf));
-		(void) fputs(buf, stdout);
-		if (p->next)
-			(void) putchar(',');
-		p = p->next;
-	}
-	(void) putchar('\n');
-}
-
-static void
-pr_ifaddrset(const struct pfil_ifaddrset *asp)
-{
-	int i;
-
-	(void) printf("addrset %s (%u):\n", asp->name, asp->af);
-
-	if (asp->nspans == 0) {
-		(void) puts(" [empty]");
-		return;
-	}
-
-	if (asp->af == AF_INET) {
-		struct pfil_v4span *p = (struct pfil_v4span *)(asp + 1);
-
-		for (i = 0; i < asp->nspans; i++) {
-			ipaddr_t addr;
-			char buf[INET_ADDRSTRLEN];
-
-			addr = htonl(p->first);
-			(void) inet_ntop(AF_INET, &addr, buf, sizeof (buf));
-			(void) printf(" %s", buf);
-
-			if (p->first != p->last) {
-				addr = htonl(p->last);
-				(void) inet_ntop(AF_INET, &addr,
-				    buf, sizeof (buf));
-				(void) printf(" - %s", buf);
-			}
-
-			if (i+1 < asp->nspans)
-				(void) putchar(',');
-			p++;
-		}
-		(void) putchar('\n');
-	} else if (asp->af == AF_INET6) {
-		struct pfil_v6span *p = (struct pfil_v6span *)(asp + 1);
-
-		for (i = 0; i < asp->nspans; i++) {
-			char buf[INET6_ADDRSTRLEN];
-
-			(void) inet_ntop(AF_INET6, &p->first,
-			    buf, sizeof (buf));
-			(void) printf(" %s", buf);
-
-			if (!IP6_EQ(&p->first, &p->last)) {
-				(void) inet_ntop(AF_INET6, &p->last,
-				    buf, sizeof (buf));
-				(void) printf(" - %s", buf);
-			}
-
-			if (i + 1 < asp->nspans)
-				(void) putchar(',');
-			p++;
-		}
-		(void) putchar('\n');
-	}
-}
-
-int
-pfil_msg(uint32_t cmd, void *buf, size_t len)
-{
-	struct pfil_ifaddrset *ifaddrset = buf;
-	pr_ifaddrset(ifaddrset);
-	return (0);
-}
-
-int
-main(int argc, char *argv[])
-{
-	int numifs, i;
-	struct pfil_ifaddrs *ifaddrlist;
-
-	numifs = argc-1;
-	if ((ifaddrlist = calloc(numifs, sizeof (ifaddrlist[0]))) == NULL)
-		return (-1);
-
-	for (i = 0; i < numifs; i++) {
-		(void) strlcpy(ifaddrlist[i].name, argv[i+1], LIFNAMSIZ);
-		ifaddrlist[i].localaddr.in.sin_family = AF_INET;
-	}
-
-	if (vas(ifaddrlist, numifs) != 0) {
-		free(ifaddrlist);
-		return (-1);
-	}
-
-	for (i = 0; i < numifs; i++) {
-		(void) strlcpy(ifaddrlist[i].name, argv[i+1], LIFNAMSIZ);
-		ifaddrlist[i].localaddr.in6.sin6_family = AF_INET6;
-	}
-	if (vas(ifaddrlist, numifs) != 0) {
-		free(ifaddrlist);
-		return (-1);
-	}
-
-	free(ifaddrlist);
-	return (0);
-}
-#endif
--- a/usr/src/cmd/ipf/svc/Makefile	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/cmd/ipf/svc/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -1,12 +1,32 @@
 #
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
 #
 
-MANIFEST=	ipfilter.xml pfil.xml 
-SVCMETHOD=	ipfilter pfil
+MANIFEST=	ipfilter.xml
+SVCMETHOD=	ipfilter
 
 include $(SRC)/cmd/Makefile.cmd
 
--- a/usr/src/cmd/ipf/svc/ipfilter	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/cmd/ipf/svc/ipfilter	Fri Oct 20 16:37:58 2006 -0700
@@ -1,5 +1,25 @@
 #!/sbin/sh
 #
+# 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
+#
+#
 # ident	"%Z%%M%	%I%	%E% SMI"
 #
 # Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
@@ -22,7 +42,6 @@
 else
 	pid=`pgrep ipmon`
 fi
-pfildpid=`pgrep pfild`
 
 logmsg()
 {
@@ -30,31 +49,9 @@
 	echo "$1" >&2
 }
 
-checkpfil()
-{
-	if [ $PFILCHECKED = yes ] ; then
-		return
-	fi
-	/usr/sbin/ndd /dev/pfil \? 2>&1 > /dev/null
-	if [ $? -ne 0 ] ; then
-		logmsg "pfil not available to support ipfilter"
-		exit $SMF_EXIT_ERR_CONFIG
-	fi
-	realnic=`/sbin/ifconfig -a modlist 2>/dev/null | grep -c pfil`
-	if [ $realnic -eq 0 ] ; then
-		logmsg "pfil not plumbed on any network interfaces."
-		logmsg "No network traffic will be filtered."
-		logmsg "See ipfilter(5) for more information."
-		exit $SMF_EXIT_ERR_CONFIG
-	fi
-	PFILCHECKED=yes
-}
-
-
 load_ipf() {
 	bad=0
 	if [ -r ${IPFILCONF} ]; then
-		checkpfil
 		ipf -IFa -f ${IPFILCONF} >/dev/null
 		if [ $? != 0 ]; then
 			echo "$0: load of ${IPFILCONF} into alternate set failed"
@@ -62,7 +59,6 @@
 		fi
 	fi
 	if [ -r ${IP6FILCONF} ]; then
-		checkpfil
 		ipf -6IFa -f ${IP6FILCONF} >/dev/null
 		if [ $? != 0 ]; then
 			echo "$0: load of ${IPFILCONF} into alternate set failed"
@@ -81,7 +77,6 @@
 
 load_ipnat() {
 	if [ -r ${IPNATCONF} ]; then
-		checkpfil
 		ipnat -CF -f ${IPNATCONF} >/dev/null
 		if [ $? != 0 ]; then
 			echo "$0: load of ${IPNATCONF} failed"
@@ -98,7 +93,6 @@
 
 load_ippool() {
 	if [ -r ${IPPOOLCONF} ]; then
-		checkpfil
 		ippool -F >/dev/null
 		ippool -f ${IPPOOLCONF} >/dev/null
 		if [ $? != 0 ]; then
@@ -116,9 +110,7 @@
 case "$1" in
 	start)
 		[ ! -f ${IPFILCONF} ] && exit 0
-		[ -n "$pfildpid" ] && kill -TERM $pfildpid 2>/dev/null
 		[ -n "$pid" ] && kill -TERM $pid 2>/dev/null
-		/usr/sbin/pfild >/dev/null
 		if load_ippool && load_ipf && load_ipnat ; then
 			/usr/sbin/ipmon -Ds
 		else
@@ -127,7 +119,6 @@
 		;;
 
 	stop)
-		[ -n "$pfildpid" ] && kill -TERM $pfildpid
 		[ -n "$pid" ] && kill -TERM $pid
 		;;
 
--- a/usr/src/cmd/ipf/svc/ipfilter.xml	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/cmd/ipf/svc/ipfilter.xml	Fri Oct 20 16:37:58 2006 -0700
@@ -1,8 +1,27 @@
 <?xml version="1.0"?>
 <!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
 <!--
-	Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
-	Use is subject to license terms.
+ Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ Use is subject to license terms.
+
+ 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
 
 	ident	"%Z%%M%	%I%	%E% SMI"
 
@@ -42,14 +61,6 @@
 	</dependency>
 
 	<dependency
-	    name='pfil'
-	    grouping='require_all'
-	    restart_on='restart'
-	    type='service'>
-		<service_fmri value='svc:/network/pfil' />
-	</dependency>
-
-	<dependency
 	    name='physical'
 	    grouping='require_all'
 	    restart_on='restart'
--- a/usr/src/cmd/ipf/svc/pfil	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-#!/sbin/sh
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-
-#
-# Autopush pfil on to filtering interfaces and restrict
-# network traffic during startup
-#
-
-
-PFILAP=/etc/ipf/pfil.ap
-
-case "$1" in
-'start')
-	/sbin/autopush -f ${PFILAP}
-	enabled=`svcprop -c -p general/enabled svc:/network/ipfilter:default`
-
-	# To avoid a window of vulnerability during the time that networking
-	# is being initialized but before the full ipf.conf configuration is
-	# loaded, install a temporary, restrictive rule set now, early in
-	# boot.  This gets replaced by the contents of ipf.conf when the
-	# svc:/network/ipfilter service is started.  Note that if /usr is not
-	# mounted, the window of vulnerability still exists because we can't
-	# run the ipf command this early.
-
-	if [ -x /usr/sbin/ipf ] && [ "$enabled" = "true" ]; then
-		echo "block in all" | /usr/sbin/ipf -Fa -f -
-		echo "block out all" | /usr/sbin/ipf -f -
-		echo "pass out from any to any port = 53 keep state" \
-		     | /usr/sbin/ipf -f -
-	fi
-	;;
-	
-*)
-	echo "Usage: $0 start"
-	exit 1
-	;;
-esac
-exit 0
--- a/usr/src/cmd/ipf/svc/pfil.xml	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
-<!--
-	Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
-	Use is subject to license terms.
-
-	ident	"%Z%%M%	%I%	%E% SMI"
-
-	NOTE:  This service manifest is not editable; its contents will
-	be overwritten by package or patch operations, including
-	operating system upgrade.  Make customizations in a different
-	file.
-
-	Service manifest for the pfil (packet filter) service.
--->
-
-<service_bundle type='manifest' name='SUNWipfr:pfil'>
-
-<service
-	name='network/pfil'
-	type='service'
-	version='1'>
-
-	<create_default_instance enabled='true' />
-
-	<single_instance />
-
-	<dependent
-	    name='pfil_network'
-	    grouping='optional_all'
-	    restart_on='none'>
-		<service_fmri value='svc:/network/physical' />
-	</dependent>
-
-	<dependent
-	    name='pfil_sysid'
-	    grouping='optional_all'
-	    restart_on='none'>
-		<service_fmri value='svc:/system/sysidtool:net' />
-	</dependent>
-
-	<!--
-		The stop method really should deconfigure pfil from sad(7D),
-		but autopush(1M) doesn't have the ability to remove entries
-		based on a file in the same format as it uses to add them.
-	-->
-	<exec_method
-		type='method'
-		name='stop'
-		exec=':true'
-		timeout_seconds='0' >
-	</exec_method>
-
-	<exec_method
-		type='method'
-		name='start'
-		exec='/lib/svc/method/pfil start'
-		timeout_seconds='0' >
-	</exec_method>
-
-	<property_group
-		name='startd'
-		type='framework'>
-		<propval name='duration' type='astring' value='transient' />
-	</property_group>
-
-	<stability value='Unstable' />
-
-	<template>
-		<common_name>
-			<loctext xml:lang='C'>packet filter</loctext>
-		</common_name>
-		<description>
-			<loctext xml:lang='C'>
-			Packet filter interface; autopushes the pfil STREAMS
-			module on network devices.
-			</loctext>
-		</description>
-		<documentation>
-			<manpage title='ipfilter' section='5'
-				manpath='/usr/share/man' />
-		</documentation>
-	</template>
-</service>
-
-</service_bundle>
--- a/usr/src/cmd/ipf/tools/ip_fil.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/cmd/ipf/tools/ip_fil.c	Fri Oct 20 16:37:58 2006 -0700
@@ -410,7 +410,7 @@
 		if (!(mode & FWRITE))
 			error = EPERM;
 		else {
-			frsync(NULL);
+			frsync(IPFSYNC_RESYNC, IPFSYNC_RESYNC, NULL, NULL);
 		}
 		break;
 	default :
@@ -455,7 +455,7 @@
 			f->fr_ifa = (void *)-1;
 #endif
 	RWLOCK_EXIT(&ipf_mutex);
-	fr_natsync(ifp);
+	fr_natifpsync(IPFSYNC_OLDIFP, ifp, NULL);
 }
 
 
@@ -614,7 +614,7 @@
 		*addr++ = '\0';
 
 	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
-		COPYIFNAME(ifp, ifname);
+		COPYIFNAME(ifp, ifname, 0);
 		if (!strcmp(name, ifname)) {
 			if (addr != NULL)
 				fr_setifpaddr(ifp, addr);
@@ -781,8 +781,10 @@
 }
 
 
-void frsync(ifp)
-void *ifp;
+void frsync(command, version, nic, data)
+int command, version;
+void *nic;
+char *data;
 {
 	return;
 }
--- a/usr/src/cmd/ipf/tools/ipf_y.y	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/cmd/ipf/tools/ipf_y.y	Fri Oct 20 16:37:58 2006 -0700
@@ -177,6 +177,7 @@
 
 %token	IPFY_PRI_EMERG IPFY_PRI_ALERT IPFY_PRI_CRIT IPFY_PRI_ERR IPFY_PRI_WARN
 %token	IPFY_PRI_NOTICE IPFY_PRI_INFO IPFY_PRI_DEBUG
+%token	IPFY_SET_LOOPBACK IPFY_SET
 %%
 file:	line
 	| assign
@@ -194,6 +195,7 @@
 			  resetlexer();
 			}
 	| YY_COMMENT
+	| set
 	;
 
 xx:	{ newrule(); }
@@ -210,6 +212,28 @@
 	'='				{ yyvarnext = 1; }
 	;
 
+set:
+	IPFY_SET IPFY_SET_LOOPBACK YY_STR ';'
+			{
+			  int data;
+			  if (frold != NULL) {
+				yyerror("ipf rules before \"set\"");
+				return 0;
+			  }
+			  if (!strcmp($3, "true"))
+				data = 1;
+			  else if (!strcmp($3, "false"))
+				data = 0;
+			  else {
+				yyerror("invalid argument for ipf_loopback");
+				return 0;
+			  }
+			  if (((opts & OPT_DONOTHING) == 0) &&
+			      (ioctl(ipffd, SIOCIPFLP, &data) == -1))
+				perror("ioctl(SIOCIPFLP)");
+			}
+	;
+
 rule:	inrule eol
 	| outrule eol
 	;
@@ -1560,6 +1584,7 @@
 	{ "icmp-type",			IPFY_ICMPTYPE },
 	{ "in",				IPFY_IN },
 	{ "in-via",			IPFY_INVIA },
+	{ "intercept_loopback",		IPFY_SET_LOOPBACK },
 	{ "ipopt",			IPFY_IPOPTS },
 	{ "ipopts",			IPFY_IPOPTS },
 	{ "keep",			IPFY_KEEP },
@@ -1600,6 +1625,7 @@
 	{ "route-to",			IPFY_ROUTETO },
 	{ "sec-class",			IPFY_SECCLASS },
 	{ "set-tag",			IPFY_SETTAG },
+	{ "set",			IPFY_SET },
 	{ "skip",			IPFY_SKIP },
 	{ "short",			IPFY_SHORT },
 	{ "state",			IPFY_STATE },
--- a/usr/src/cmd/mdb/Makefile.common	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/cmd/mdb/Makefile.common	Fri Oct 20 16:37:58 2006 -0700
@@ -57,6 +57,8 @@
 	crypto	\
 	dtrace	\
 	genunix \
+	hook \
+	neti \
 	ip \
 	ipc \
 	ipp \
--- a/usr/src/cmd/mdb/common/modules/arp/arp.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/cmd/mdb/common/modules/arp/arp.c	Fri Oct 20 16:37:58 2006 -0700
@@ -30,6 +30,8 @@
 #include <sys/stropts.h>
 #include <sys/stream.h>
 #include <sys/dlpi.h>
+#include <sys/hook.h>
+#include <sys/hook_event.h>
 #include <inet/led.h>
 #include <inet/common.h>
 #include <inet/mi.h>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/mdb/common/modules/hook/hook.c	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,252 @@
+/*
+ * 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 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/types.h>
+#include <sys/rwlock.h>
+#include <mdb/mdb_modapi.h>
+#include <sys/queue.h>
+#include <sys/hook.h>
+#include <sys/hook_impl.h>
+
+#define	MAX_LENGTH 64
+
+/*
+ * List pfhooks hook list information.
+ */
+/*ARGSUSED*/
+int
+hooklist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+	hook_event_int_t hr;
+	hook_int_t hl, *hlp;
+	char hrstr[MAX_LENGTH];
+	GElf_Sym sym;
+	char buf[MDB_SYM_NAMLEN + 1];
+
+	if (argc)
+		return (DCMD_USAGE);
+
+	if (mdb_vread((void *)&hr, sizeof (hr), (uintptr_t)addr) == -1) {
+		mdb_warn("couldn't read hook register at %p", addr);
+		return (DCMD_ERR);
+	}
+
+	mdb_printf("%<u>%?s %10s %20s %?s%</u>\n",
+	    "ADDR", "FLAG", "FUNC", "NAME");
+	hlp = TAILQ_FIRST(&hr.hei_head);
+	while (hlp) {
+		if (mdb_vread((void *)&hl, sizeof (hl),
+		    (uintptr_t)hlp) == -1) {
+			mdb_warn("couldn't read hook list at %p",
+			    hlp);
+			return (DCMD_ERR);
+		}
+		if (!hl.hi_hook.h_name) {
+			mdb_warn("hook list at %p has null role",
+			    hl.hi_hook);
+			return (DCMD_ERR);
+		}
+		if (mdb_readstr((char *)hrstr, sizeof (hrstr),
+		    (uintptr_t)hl.hi_hook.h_name) == -1) {
+			mdb_warn("couldn't read list role at %p",
+			    hl.hi_hook.h_name);
+			return (DCMD_ERR);
+		}
+		if (mdb_lookup_by_addr((uintptr_t)hl.hi_hook.h_func,
+		    MDB_SYM_EXACT, buf, sizeof (buf), &sym) == -1)
+			mdb_printf("%0?p %10x %0?p %10s\n",
+			    hlp, hl.hi_hook.h_flags, hl.hi_hook.h_func, hrstr);
+		else
+			mdb_printf("%0?p %10x %20s %10s\n",
+			    hlp, hl.hi_hook.h_flags, buf, hrstr);
+		hlp = TAILQ_NEXT(&hl, hi_entry);
+	}
+	return (DCMD_OK);
+}
+
+
+/*
+ * List pfhooks event information.
+ * List the hooks information in verbose mode as well.
+ */
+/*ARGSUSED*/
+int
+hookeventlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+	hook_family_int_t hf;
+	hook_event_int_t hr, *hrp;
+	hook_event_t hp;
+	char hprstr[MAX_LENGTH];
+
+	if (argc)
+		return (DCMD_USAGE);
+
+	if (mdb_vread((void *)&hf, sizeof (hf), (uintptr_t)addr) == -1) {
+		mdb_warn("couldn't read hook family at %p", addr);
+		return (DCMD_ERR);
+	}
+
+	mdb_printf("%<u>%?s %10s %20s%</u>\n", "ADDR", "FLAG", "NAME");
+	hrp = SLIST_FIRST(&hf.hfi_head);
+	while (hrp) {
+		if (mdb_vread((void *)&hr, sizeof (hr), (uintptr_t)hrp) == -1) {
+			mdb_warn("couldn't read hook register at %p", hrp);
+			return (DCMD_ERR);
+		}
+		if (!hr.hei_event) {
+			mdb_warn("hook register at %p has no hook provider",
+			    hrp);
+			return (DCMD_ERR);
+		}
+		if (mdb_vread((void *)&hp, sizeof (hp),
+		    (uintptr_t)hr.hei_event) == -1) {
+			mdb_warn("hook provider at %p has null role",
+			    hr.hei_event);
+			return (DCMD_ERR);
+		}
+		if (!hp.he_name) {
+			mdb_warn("hook provider at %p has null role",
+			    hr.hei_event);
+			return (DCMD_ERR);
+		}
+		if (mdb_readstr((char *)hprstr, sizeof (hprstr),
+		    (uintptr_t)hp.he_name) == -1) {
+			mdb_warn("couldn't read provider role at %p",
+			    hp.he_name);
+			return (DCMD_ERR);
+		}
+		mdb_printf("%0?p %10x %20s\n", hrp, hp.he_flags, hprstr);
+		hrp = SLIST_NEXT(&hr, hei_entry);
+	}
+
+	return (DCMD_OK);
+}
+
+/*
+ * List pfhooks family information.
+ */
+/*ARGSUSED*/
+int
+hookrootlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+	hook_family_int_head_t hfh;
+	hook_family_int_t hf, *hfp;
+	char hrrstr[MAX_LENGTH];
+
+	if (argc)
+		return (DCMD_USAGE);
+
+	if (mdb_readvar(&hfh, "familylist") == -1) {
+		mdb_warn("couldn't read symbol 'familylist'");
+		return (DCMD_ERR);
+	}
+
+	mdb_printf("%<u>%?s %10s%</u>\n", "ADDR", "FAMILY");
+	hfp = SLIST_FIRST(&hfh);
+	while (hfp) {
+		if (mdb_vread((void *)&hf, sizeof (hf), (uintptr_t)hfp) == -1) {
+			mdb_warn("couldn't read hook family at %p", hfp);
+			return (DCMD_ERR);
+		}
+		if (!hf.hfi_family.hf_name) {
+			mdb_warn("hook root at %p has null role",
+			    hf.hfi_family);
+			return (DCMD_ERR);
+		}
+		if (mdb_readstr((char *)hrrstr, sizeof (hrrstr),
+		    (uintptr_t)hf.hfi_family.hf_name) == -1) {
+			mdb_warn("couldn't read root role at %p",
+			    hf.hfi_family.hf_name);
+			return (DCMD_ERR);
+		}
+		mdb_printf("%0?p %10s\n", hfp, hrrstr);
+		hfp = SLIST_NEXT(&hf, hfi_entry);
+	}
+
+	return (DCMD_OK);
+}
+
+
+static int
+hookevent_walk_init(mdb_walk_state_t *wsp)
+{
+	hook_family_int_t hf;
+
+	if (wsp->walk_addr == NULL) {
+		mdb_warn("global walk not supported\n");
+		return (WALK_ERR);
+	}
+
+	if (mdb_vread((void *)&hf, sizeof (hf),
+	    (uintptr_t)wsp->walk_addr) == -1) {
+		mdb_warn("couldn't read hook family at %p", wsp->walk_addr);
+		return (DCMD_ERR);
+	}
+	wsp->walk_addr = (uintptr_t)SLIST_FIRST(&hf.hfi_head);
+	return (wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
+		    wsp->walk_cbdata));
+}
+
+static int
+hookevent_walk_step(mdb_walk_state_t *wsp)
+{
+	hook_event_int_t hr;
+
+	if (mdb_vread((void *)&hr, sizeof (hr),
+	    (uintptr_t)wsp->walk_addr) == -1) {
+		mdb_warn("couldn't read hook event at %p", wsp->walk_addr);
+		return (DCMD_ERR);
+	}
+	wsp->walk_addr = (uintptr_t)SLIST_NEXT(&hr, hei_entry);
+	if (wsp->walk_addr == NULL)
+		return (WALK_DONE);
+	return (wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
+		    wsp->walk_cbdata));
+}
+
+
+static const mdb_dcmd_t dcmds[] = {
+	{ "hookrootlist", "", "display hook family information", hookrootlist },
+	{ "hookeventlist", "", "display hook event information",
+		hookeventlist, NULL },
+	{ "hooklist", "", "display hooks", hooklist },
+	{ NULL }
+};
+
+static const mdb_walker_t walkers[] = {
+	{ "hookevent", "walk a list of hooks",
+		hookevent_walk_init, hookevent_walk_step, NULL },
+	{ NULL }
+};
+
+static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
+
+const mdb_modinfo_t *
+_mdb_init(void)
+{
+	return (&modinfo);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/mdb/common/modules/neti/neti.c	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,103 @@
+/*
+ * 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 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/types.h>
+#include <sys/rwlock.h>
+#include <mdb/mdb_modapi.h>
+#include <sys/queue.h>
+#include <sys/neti.h>
+
+
+/*
+ * PROT_LENGTH is the max length. If the true length is bigger
+ * it is truncated.
+ */
+#define	PROT_LENGTH 32
+
+LIST_HEAD(netd_listhead, net_data);
+
+/*
+ * List pfhooks netinfo information.
+ */
+/*ARGSUSED*/
+int
+netinfolist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+	struct netd_listhead nlh;
+	struct net_data nd, *p;
+	char str[PROT_LENGTH];
+
+	if (argc)
+		return (DCMD_USAGE);
+
+	if (mdb_readvar(&nlh, "netd_head") == -1) {
+		mdb_warn("couldn't read symbol 'netd_head'");
+		return (DCMD_ERR);
+	}
+	mdb_printf("%<u>%?s %?s %10s%</u>\n",
+	    "ADDR(netinfo)", "ADDR(hookevent)", "netinfo");
+	p = LIST_FIRST(&nlh);
+	while (p) {
+		if (mdb_vread((void *)&nd, sizeof (nd), (uintptr_t)p) == -1) {
+			mdb_warn("couldn't read netinfo at %p", p);
+			return (DCMD_ERR);
+		}
+		if (!nd.netd_info.neti_protocol) {
+			mdb_warn("netinfo at %p has null protocol",
+			    nd.netd_info.neti_protocol);
+			return (DCMD_ERR);
+		}
+		if (mdb_readstr((char *)str, sizeof (str),
+		    (uintptr_t)nd.netd_info.neti_protocol) == -1) {
+			mdb_warn("couldn't read protocol at %p",
+			    nd.netd_info.neti_protocol);
+			return (DCMD_ERR);
+		}
+
+		mdb_printf("%0?p %0?p %10s\n",
+		    (char *)p + (uintptr_t)&((struct net_data *)0)->netd_info,
+		    nd.netd_hooks, str);
+
+		p = LIST_NEXT(&nd, netd_list);
+	}
+
+	return (DCMD_OK);
+}
+
+static const mdb_dcmd_t dcmds[] = {
+	{ "netinfolist", "", "display netinfo information",
+		netinfolist, NULL },
+	{ NULL }
+};
+
+static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds };
+
+const mdb_modinfo_t *
+_mdb_init(void)
+{
+	return (&modinfo);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/mdb/intel/amd64/hook/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,35 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+
+MODULE = hook.so
+MDBTGT = kvm
+
+MODSRCS = hook.c
+
+include ../../../../Makefile.cmd
+include ../../../../Makefile.cmd.64
+include ../../Makefile.amd64
+include ../../../Makefile.module
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/mdb/intel/amd64/neti/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,35 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+
+MODULE = neti.so
+MDBTGT = kvm
+
+MODSRCS = neti.c
+
+include ../../../../Makefile.cmd
+include ../../../../Makefile.cmd.64
+include ../../Makefile.amd64
+include ../../../Makefile.module
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/mdb/intel/ia32/hook/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,34 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+
+MODULE = hook.so
+MDBTGT = kvm
+
+MODSRCS = hook.c
+
+include ../../../../Makefile.cmd
+include ../../Makefile.ia32
+include ../../../Makefile.module
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/mdb/intel/ia32/neti/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,34 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+
+MODULE = neti.so
+MDBTGT = kvm
+
+MODSRCS = neti.c
+
+include ../../../../Makefile.cmd
+include ../../Makefile.ia32
+include ../../../Makefile.module
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/mdb/sparc/v9/hook/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,35 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+
+MODULE = hook.so
+MDBTGT = kvm
+
+MODSRCS = hook.c
+
+include ../../../../Makefile.cmd
+include ../../../../Makefile.cmd.64
+include ../../Makefile.sparcv9
+include ../../../Makefile.module
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/mdb/sparc/v9/neti/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,35 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+
+MODULE = neti.so
+MDBTGT = kvm
+
+MODSRCS = neti.c
+
+include ../../../../Makefile.cmd
+include ../../../../Makefile.cmd.64
+include ../../Makefile.sparcv9
+include ../../../Makefile.module
--- a/usr/src/cmd/svc/prophist/prophist.SUNWcsr	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/cmd/svc/prophist/prophist.SUNWcsr	Fri Oct 20 16:37:58 2006 -0700
@@ -3,9 +3,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# 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.
@@ -21,7 +20,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
@@ -412,9 +411,6 @@
 instance_refresh svc:/network/ntp:default
 instance_refresh svc:/milestone/multi-user:default
 
-prophist_upgrade network/pfil start exec \
-    "/lib/svc/method/pfil start" "/sbin/autopush -f /etc/ipf/pfil.ap"
-
 prophist_upgrade network/rarp start timeout_seconds 60 3
 prophist_upgrade network/rarp stop timeout_seconds 60 3
 prophist_adddpt svc:/network/rarp rarp_multi-user-server optional_all none \
--- a/usr/src/cmd/svc/seed/Makefile	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/cmd/svc/seed/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -75,8 +75,7 @@
 	../milestone/multi-user-server.xml \
 	../../cmd-inet/usr.lib/inetd/inetd-upgrade.xml \
 	../../utmpd/utmp.xml \
-	../../lvm/util/metainit.xml \
-	../../ipf/svc/pfil.xml
+	../../lvm/util/metainit.xml
 
 #
 # Additional manifests for a Solaris zone
--- a/usr/src/cmd/svc/seed/inc.flg	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/cmd/svc/seed/inc.flg	Fri Oct 20 16:37:58 2006 -0700
@@ -3,9 +3,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# 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.
@@ -21,7 +20,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -32,5 +31,4 @@
 echo_file usr/src/cmd/utmpd/utmp.xml
 echo_file usr/src/cmd/lvm/util/metainit.xml
 echo_file usr/src/cmd/lvm/md_monitord/mdmonitor.xml
-echo_file usr/src/cmd/ipf/svc/pfil.xml
 find_files "s.*.xml" usr/src/cmd/svc/milestone
--- a/usr/src/lib/libsecdb/exec_attr.txt	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/lib/libsecdb/exec_attr.txt	Fri Oct 20 16:37:58 2006 -0700
@@ -107,7 +107,6 @@
 IP Filter Management:solaris:cmd:::/usr/sbin/ipfstat:privs=sys_net_config;gid=sys
 IP Filter Management:solaris:cmd:::/usr/sbin/ipnat:privs=sys_net_config;gid=sys
 IP Filter Management:solaris:cmd:::/usr/sbin/ippool:privs=sys_net_config;gid=sys
-IP Filter Management:solaris:cmd:::/usr/sbin/pfild:uid=0
 Kerberos Server Management:solaris:cmd:::/usr/lib/krb5/krb5kdc:uid=0
 Kerberos Server Management:solaris:cmd:::/usr/lib/krb5/kadmind:uid=0
 Kerberos Server Management:solaris:cmd:::/usr/lib/krb5/kprop:euid=0;privs=none
--- a/usr/src/pkgdefs/SUNWckr/prototype_i386	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/pkgdefs/SUNWckr/prototype_i386	Fri Oct 20 16:37:58 2006 -0700
@@ -159,6 +159,7 @@
 f none kernel/misc/dls 755 root sys
 f none kernel/misc/fssnap_if 755 root sys
 f none kernel/misc/gld 755 root sys
+f none kernel/misc/hook 755 root sys
 f none kernel/misc/hpcsvc 755 root sys
 f none kernel/misc/i2o_msg 755 root sys
 f none kernel/misc/ipc 755 root sys
@@ -168,6 +169,7 @@
 f none kernel/misc/krtld 755 root sys
 f none kernel/misc/mac 755 root sys
 l none kernel/misc/md5=../../kernel/crypto/md5
+f none kernel/misc/neti 755 root sys
 f none kernel/misc/pcicfg 755 root sys
 f none kernel/misc/pcihp 755 root sys
 f none kernel/misc/pcmcia 755 root sys
@@ -333,6 +335,7 @@
 f none kernel/misc/amd64/dls 755 root sys
 f none kernel/misc/amd64/fssnap_if 755 root sys
 f none kernel/misc/amd64/gld 755 root sys
+f none kernel/misc/amd64/hook 755 root sys
 f none kernel/misc/amd64/hpcsvc 755 root sys
 f none kernel/misc/amd64/ipc 755 root sys
 f none kernel/misc/amd64/kbtrans 755 root sys
@@ -341,6 +344,7 @@
 f none kernel/misc/amd64/krtld 755 root sys
 f none kernel/misc/amd64/mac 755 root sys
 l none kernel/misc/amd64/md5=../../../kernel/crypto/amd64/md5
+f none kernel/misc/amd64/neti 755 root sys
 f none kernel/misc/amd64/pcicfg 755 root sys
 f none kernel/misc/amd64/pcihp 755 root sys
 f none kernel/misc/amd64/pcmcia 755 root sys
--- a/usr/src/pkgdefs/SUNWckr/prototype_sparc	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/pkgdefs/SUNWckr/prototype_sparc	Fri Oct 20 16:37:58 2006 -0700
@@ -168,6 +168,7 @@
 f none kernel/misc/sparcv9/dls 755 root sys
 f none kernel/misc/sparcv9/fssnap_if 755 root sys
 f none kernel/misc/sparcv9/gld 755 root sys
+f none kernel/misc/sparcv9/hook 755 root sys
 f none kernel/misc/sparcv9/hpcsvc 755 root sys
 f none kernel/misc/sparcv9/ipc 755 root sys
 f none kernel/misc/sparcv9/kbtrans 755 root sys
@@ -175,6 +176,7 @@
 f none kernel/misc/sparcv9/krtld 755 root sys
 f none kernel/misc/sparcv9/mac 755 root sys
 l none kernel/misc/sparcv9/md5=../../../kernel/crypto/sparcv9/md5
+f none kernel/misc/sparcv9/neti 755 root sys
 f none kernel/misc/sparcv9/pcie 755 root sys
 f none kernel/misc/sparcv9/pcihp 755 root sys
 f none kernel/misc/sparcv9/pciehpc 755 root sys
--- a/usr/src/pkgdefs/SUNWhea/prototype_com	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/pkgdefs/SUNWhea/prototype_com	Fri Oct 20 16:37:58 2006 -0700
@@ -139,6 +139,7 @@
 f none usr/include/inet/ip_ire.h 644 root bin
 f none usr/include/inet/ip_ftable.h 644 root bin
 f none usr/include/inet/ip_multi.h 644 root bin
+f none usr/include/inet/ip_netinfo.h 644 root bin
 f none usr/include/inet/ip_rts.h 644 root bin
 f none usr/include/inet/ip6.h 644 root bin
 f none usr/include/inet/ip6_asp.h 644 root bin
@@ -750,6 +751,9 @@
 f none usr/include/sys/ftrace.h 644 root bin
 f none usr/include/sys/gfs.h 644 root bin
 f none usr/include/sys/hdio.h 644 root bin
+f none usr/include/sys/hook.h 644 root bin
+f none usr/include/sys/hook_event.h 644 root bin
+f none usr/include/sys/hook_impl.h 644 root bin
 f none usr/include/sys/hwconf.h 644 root bin
 f none usr/include/sys/ia.h 644 root bin
 f none usr/include/sys/iapriocntl.h 644 root bin
@@ -892,6 +896,7 @@
 f none usr/include/sys/nexusdefs.h 644 root bin
 f none usr/include/sys/ndifm.h 644 root bin
 f none usr/include/sys/ndi_impldefs.h 644 root bin
+f none usr/include/sys/neti.h 644 root bin
 f none usr/include/sys/note.h 644 root bin
 f none usr/include/sys/nvpair.h 644 root bin
 f none usr/include/sys/nvpair_impl.h 644 root bin
@@ -960,6 +965,7 @@
 f none usr/include/sys/ptem.h 644 root bin
 f none usr/include/sys/ptms.h 644 root bin
 f none usr/include/sys/ptyvar.h 644 root bin
+f none usr/include/sys/queue.h 644 root bin
 f none usr/include/sys/raidioctl.h 644 root bin
 f none usr/include/sys/ramdisk.h 644 root bin
 f none usr/include/sys/random.h 644 root bin
--- a/usr/src/pkgdefs/SUNWipfr/prototype_com	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/pkgdefs/SUNWipfr/prototype_com	Fri Oct 20 16:37:58 2006 -0700
@@ -1,3 +1,23 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
@@ -28,16 +48,13 @@
 #
 d none etc 755 root sys
 d none etc/ipf 755 root sys
-e preserve etc/ipf/pfil.ap 644 root sys
 e preserve etc/ipf/ipf.conf 644 root sys
 d none lib 755 root bin
 d none lib/svc 0755 root bin
 d none lib/svc/method 0755 root bin
 f none lib/svc/method/ipfilter 0555 root bin
-f none lib/svc/method/pfil 0555 root bin
 d none kernel 755 root sys
 d none kernel/drv 755 root sys
-f none kernel/drv/pfil.conf 644 root sys
 d none kernel/strmod 755 root sys
 d none var 755 root sys
 d none var/db 755 root sys
@@ -45,5 +62,4 @@
 d none var/svc 755 root sys
 d none var/svc/manifest 755 root sys
 d none var/svc/manifest/network 755 root sys
-f manifest var/svc/manifest/network/pfil.xml 444 root sys
 f manifest var/svc/manifest/network/ipfilter.xml 444 root sys
--- a/usr/src/pkgdefs/SUNWipfr/prototype_i386	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/pkgdefs/SUNWipfr/prototype_i386	Fri Oct 20 16:37:58 2006 -0700
@@ -1,5 +1,25 @@
 #
-# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -28,9 +48,3 @@
 #
 # SUNWipfr
 #
-f none kernel/drv/pfil 755 root sys
-l none kernel/strmod/pfil=../../kernel/drv/pfil
-d none kernel/drv/amd64 755 root sys
-f none kernel/drv/amd64/pfil 755 root sys
-d none kernel/strmod/amd64 755 root sys
-l none kernel/strmod/amd64/pfil=../../../kernel/drv/amd64/pfil
--- a/usr/src/pkgdefs/SUNWipfr/prototype_sparc	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/pkgdefs/SUNWipfr/prototype_sparc	Fri Oct 20 16:37:58 2006 -0700
@@ -1,5 +1,25 @@
 #
-# Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
@@ -23,10 +43,6 @@
 #
 # List files which are SPARC specific here
 #
-d none kernel/drv/sparcv9 755 root sys
-f none kernel/drv/sparcv9/pfil 755 root sys
-d none kernel/strmod/sparcv9 755 root sys
-l none kernel/strmod/sparcv9/pfil=../../../kernel/drv/sparcv9/pfil
 #
 # source locations relative to the prototype file
 #
--- a/usr/src/pkgdefs/SUNWipfu/prototype_com	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/pkgdefs/SUNWipfu/prototype_com	Fri Oct 20 16:37:58 2006 -0700
@@ -1,5 +1,25 @@
 #
-# Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
@@ -28,8 +48,8 @@
 d none usr/lib/ipf 755 root bin
 f none usr/lib/ipf/IPFILTER.LICENCE 644 root bin
 l none usr/lib/ipf/ipftest=../../../usr/lib/isaexec
-d none usr/kernel 755 root sys
-d none usr/kernel/drv 755 root sys
+d none usr/kernel 755 root sys 
+d none usr/kernel/drv 755 root sys 
 f none usr/kernel/drv/ipf.conf 644 root sys
 d none usr/sbin 755 root bin
 l none usr/sbin/ipf=../../usr/lib/isaexec
@@ -38,7 +58,6 @@
 l none usr/sbin/ipmon=../../usr/lib/isaexec
 l none usr/sbin/ipnat=../../usr/lib/isaexec
 l none usr/sbin/ippool=../../usr/lib/isaexec
-f none usr/sbin/pfild 555 root bin
 d none usr/share 755 root sys
 d none usr/share/ipfilter 755 root bin
 d none usr/share/ipfilter/examples 755 root bin
--- a/usr/src/pkgdefs/SUNWipfu/prototype_i386	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/pkgdefs/SUNWipfu/prototype_i386	Fri Oct 20 16:37:58 2006 -0700
@@ -1,5 +1,25 @@
 #
-# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
--- a/usr/src/pkgdefs/SUNWipfu/prototype_sparc	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/pkgdefs/SUNWipfu/prototype_sparc	Fri Oct 20 16:37:58 2006 -0700
@@ -1,5 +1,25 @@
 #
-# Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
--- a/usr/src/pkgdefs/SUNWmdb/prototype_i386	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/pkgdefs/SUNWmdb/prototype_i386	Fri Oct 20 16:37:58 2006 -0700
@@ -53,6 +53,8 @@
 f none usr/lib/mdb/kvm/amd64/crypto.so 555 root sys
 f none usr/lib/mdb/kvm/amd64/genunix.so 555 root sys
 f none usr/lib/mdb/kvm/amd64/ip.so 555 root sys
+f none usr/lib/mdb/kvm/amd64/hook.so 555 root sys
+f none usr/lib/mdb/kvm/amd64/neti.so 555 root sys
 f none usr/lib/mdb/kvm/amd64/ipc.so 555 root sys
 f none usr/lib/mdb/kvm/amd64/ipp.so 555 root sys
 f none usr/lib/mdb/kvm/amd64/krtld.so 555 root sys
@@ -78,6 +80,8 @@
 f none usr/lib/mdb/kvm/crypto.so 555 root sys
 f none usr/lib/mdb/kvm/genunix.so 555 root sys
 f none usr/lib/mdb/kvm/ip.so 555 root sys
+f none usr/lib/mdb/kvm/hook.so 555 root sys
+f none usr/lib/mdb/kvm/neti.so 555 root sys
 f none usr/lib/mdb/kvm/ipc.so 555 root sys
 f none usr/lib/mdb/kvm/ipp.so 555 root sys
 f none usr/lib/mdb/kvm/krtld.so 555 root sys
--- a/usr/src/pkgdefs/SUNWmdb/prototype_sparc	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/pkgdefs/SUNWmdb/prototype_sparc	Fri Oct 20 16:37:58 2006 -0700
@@ -45,6 +45,8 @@
 f none usr/lib/mdb/kvm/sparcv9/genunix.so 555 root sys
 f none usr/lib/mdb/kvm/sparcv9/intr.so 555 root sys
 f none usr/lib/mdb/kvm/sparcv9/ip.so 555 root sys
+f none usr/lib/mdb/kvm/sparcv9/hook.so 555 root sys
+f none usr/lib/mdb/kvm/sparcv9/neti.so 555 root sys
 f none usr/lib/mdb/kvm/sparcv9/ipc.so 555 root sys
 f none usr/lib/mdb/kvm/sparcv9/ipp.so 555 root sys
 f none usr/lib/mdb/kvm/sparcv9/isp.so 555 root sys
--- a/usr/src/pkgdefs/SUNWmdbr/prototype_i386	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/pkgdefs/SUNWmdbr/prototype_i386	Fri Oct 20 16:37:58 2006 -0700
@@ -34,6 +34,8 @@
 f none kernel/kmdb/amd64/crypto 555 root sys
 f none kernel/kmdb/amd64/genunix 555 root sys
 f none kernel/kmdb/amd64/ip 555 root sys
+f none kernel/kmdb/amd64/hook 555 root sys
+f none kernel/kmdb/amd64/neti 555 root sys
 f none kernel/kmdb/amd64/ipc 555 root sys
 f none kernel/kmdb/amd64/ipp 555 root sys
 f none kernel/kmdb/amd64/krtld 555 root sys
@@ -59,6 +61,8 @@
 f none kernel/kmdb/crypto 555 root sys
 f none kernel/kmdb/genunix 555 root sys
 f none kernel/kmdb/ip 555 root sys
+f none kernel/kmdb/hook 555 root sys
+f none kernel/kmdb/neti 555 root sys
 f none kernel/kmdb/ipc 555 root sys
 f none kernel/kmdb/ipp 555 root sys
 f none kernel/kmdb/krtld 555 root sys
--- a/usr/src/pkgdefs/SUNWmdbr/prototype_sparc	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/pkgdefs/SUNWmdbr/prototype_sparc	Fri Oct 20 16:37:58 2006 -0700
@@ -35,6 +35,8 @@
 f none kernel/kmdb/sparcv9/genunix 555 root sys
 f none kernel/kmdb/sparcv9/intr 555 root sys
 f none kernel/kmdb/sparcv9/ip 555 root sys
+f none kernel/kmdb/sparcv9/hook 555 root sys
+f none kernel/kmdb/sparcv9/neti 555 root sys
 f none kernel/kmdb/sparcv9/ipc 555 root sys
 f none kernel/kmdb/sparcv9/ipp 555 root sys
 f none kernel/kmdb/sparcv9/isp 555 root sys
--- a/usr/src/tools/scripts/bfu.sh	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/tools/scripts/bfu.sh	Fri Oct 20 16:37:58 2006 -0700
@@ -316,7 +316,6 @@
 	lib/libmeta.so
 	lib/libmeta.so.1
 	lib/svc/method/ipfilter
-	lib/svc/method/pfil
 	lib/svc/method/sf880dr
 	lib/svc/method/svc-cvcd
 	lib/svc/method/svc-dcs
@@ -377,7 +376,6 @@
 	var/db/ipf
 	var/log/pool
 	var/svc/manifest/network/ipfilter.xml
-	var/svc/manifest/network/pfil.xml
 	var/svc/manifest/network/rpc/mdcomm.xml
 	var/svc/manifest/network/rpc/meta.xml
 	var/svc/manifest/network/rpc/metamed.xml
@@ -893,7 +891,6 @@
 	etc/init.d/nodename
 	etc/init.d/nscd
 	etc/init.d/perf
-	etc/init.d/pfil
 	etc/init.d/picld
 	etc/init.d/power
 	etc/init.d/rcapd
@@ -1052,7 +1049,6 @@
 	etc/rcS.d/K43inet
 	etc/rcS.d/K99libc.mount
 	etc/rcS.d/S10cvc
-	etc/rcS.d/S10pfil
 	etc/rcS.d/S28network.sh
 	etc/rcS.d/S29nodename.sh
 	etc/rcS.d/S30rootusr.sh
@@ -1071,6 +1067,7 @@
 	var/svc/manifest/network/tftp.xml
 	var/svc/manifest/network/lp.xml
 	var/svc/manifest/system/filesystem/volfs.xml
+	var/svc/manifest/network/pfil.xml
 "
 
 # smf services whose manifests have been renamed
@@ -1083,6 +1080,7 @@
 smf_obsolete_methods="
 	lib/svc/method/print-server
 	lib/svc/method/svc-volfs
+	lib/svc/method/pfil
 "
 
 smf_cleanup () {
@@ -1706,47 +1704,32 @@
 	fi
 
 	# If we're in the global zone, and using an alternate root, see if
-	# we are in an smf root.  If so, import pfil and name-service-cache.
-	# If we're not bfu'ing an alternate root, and we're post-smf,
-	# import pfil and name-service-cache.  This is to get pfil and
-	# name-service-cache(with correct dependencies) in the repository
-	# before reboot.  If we're bfu'ing from pre-smf, this isn't an
-	# issue, as pfil is in the seed repository, and name-service-cache
-	# will be installed with correct dependencies.
+	# we are in an smf root.  If so, import name-service-cache. If we're
+	# not bfu'ing an alternate root, and we're post-smf, import
+	# name-service-cache.  This is to get name-service-cache(with correct
+	# dependencies) in the repository before reboot.  If we're bfu'ing
+	# from pre-smf, this isn't an issue, as name-service-cache will be
+	# installed with correct dependencies.
 	if [[ $zone = global &&
-	    -f $rootprefix/var/svc/manifest/network/pfil.xml ]]; then
+	    -f $rootprefix/var/svc/manifest/system/name-service-cache.xml ]];
+	    then
 		if [[ -n $rootprefix ]]; then
 			if [ -x /usr/sbin/svccfg ]; then
 			SVCCFG_REPOSITORY=$rootprefix/etc/svc/repository.db
 			/usr/sbin/svccfg import \
-			    $rootprefix/var/svc/manifest/network/pfil.xml
-			/usr/sbin/svccfg import \
 		    $rootprefix/var/svc/manifest/system/name-service-cache.xml
 			else
-			echo "Warning: This system does not have SMF, so I"
-			echo "cannot ensure the pre-import of pfil and"
-			echo "name-service-cache.  If ipfilter or name-service-"
-			echo "cache do not work, reboot your alternate root to"
-			echo "fix it."
+			echo "Warning: This system does not have SMF, so I "
+			echo "cannot ensure the pre-import of "
+			echo "name-service-cache.  If name-service-cache does "
+			echo "not work, reboot your alternate root to fix it."
 			fi
 		elif [ -x /tmp/bfubin/svccfg ]; then
 			/tmp/bfubin/svccfg import \
-			    /var/svc/manifest/network/pfil.xml
-			/tmp/bfubin/svccfg import \
 			    /var/svc/manifest/system/name-service-cache.xml
 		fi
 	fi
 
-	# Remove pfil from the non-global repository.
-	if [[ $zone != global ]]; then
-		cat >> $rootprefix/var/svc/profile/upgrade << EOF
-		svcprop -q -p start/exec network/pfil
-		if [[ \$? = 0 ]]; then
-			/usr/sbin/svccfg delete -f network/pfil
-		fi
-EOF
-	fi
-
 	# If we're in the global zone, and using an alternate root, see if
 	# we are in an smf root.  If so, import datalink and aggregation svcs.
 	# If we're not bfu'ing an alternate root, and we're post-smf,
@@ -5992,6 +5975,13 @@
 	rm -f $root/platform/i86pc/kernel/drv/amd64/bscv
 	rm -f $root/platform/i86pc/kernel/drv/amd64/bscbus
 
+	# Remove obsolete pfil modules, binaries, and configuration files
+	rm -f $root/kernel/drv/pfil
+	rm -f $root/kernel/drv/pfil.conf
+	rm -f $root/kernel/drv/sparcv9/pfil
+	rm -f $root/kernel/drv/amd64/pfil
+	rm -f $root/usr/sbin/pfild
+
 	# Remove obsolete atomic_prim.h file.
 	rm -f $usr/include/v9/sys/atomic_prim.h
 
--- a/usr/src/uts/common/Makefile.files	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/Makefile.files	Fri Oct 20 16:37:58 2006 -0700
@@ -430,7 +430,7 @@
 
 TSWTCL_OBJS +=	tswtcl.o tswtclddi.o
 
-ARP_OBJS +=	arpddi.o arp.o
+ARP_OBJS +=	arpddi.o arp.o arp_netinfo.o
 
 ICMP_OBJS +=	icmpddi.o icmp.o icmp_opt_data.o
 
@@ -447,7 +447,7 @@
 		sctp_param.o sctp_shutdown.o sctp_common.o \
 		sctp_timer.o sctp_heartbeat.o sctp_hash.o \
 		sctp_ioc.o sctp_bind.o sctp_notify.o sctp_asconf.o \
-		sctp_addr.o tn_ipopt.o tnet.o
+		sctp_addr.o tn_ipopt.o tnet.o ip_netinfo.o
 
 IP_OBJS +=	igmp.o ip.o ip6.o ip6_asp.o ip6_if.o ip6_ire.o ip6_rts.o \
 		ip_cksum.o ip_if.o ip_ire.o ip_listutils.o ip_mroute.o \
@@ -461,6 +461,10 @@
 
 IP6_OBJS +=	ip6ddi.o
 
+HOOK_OBJS +=	hook.o
+
+NETI_OBJS +=	neti.o
+
 KEYSOCK_OBJS +=	keysockddi.o keysock.o keysock_opt_data.o
 
 SPDSOCK_OBJS += spdsockddi.o spdsock.o spdsock_opt_data.o
@@ -956,7 +960,7 @@
 
 PCKT_OBJS +=	pckt.o
 
-PFMOD_OBJS	+=	pfmod.o
+PFMOD_OBJS +=	pfmod.o
 
 PTEM_OBJS +=	ptem.o
 
@@ -1242,10 +1246,8 @@
 
 IPF_OBJS += ip_fil_solaris.o fil.o solaris.o ip_state.o ip_frag.o ip_nat.o \
 	    ip_proxy.o ip_auth.o ip_pool.o ip_htable.o ip_lookup.o \
-	    ip_log.o
+	    ip_log.o misc.o
  
-PFIL_OBJS +=  pfil.o qif.o pfildrv.o pfilstream.o pkt.o misc.o ndd.o
-
 IBD_OBJS +=	ibd.o
 
 VNI_OBJS += vni.o
--- a/usr/src/uts/common/Makefile.rules	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/Makefile.rules	Fri Oct 20 16:37:58 2006 -0700
@@ -370,9 +370,8 @@
 	$(CTFCONVERT_O)
 
 
-IPFFLAGS=-I $(UTSBASE)/common/inet/pfil
 $(OBJS_DIR)/%.o:		$(UTSBASE)/common/inet/ipf/%.c
-	$(COMPILE.c) $(IPFFLAGS) -o $@ $<
+	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
 
 $(OBJS_DIR)/%.o:		$(COMMONBASE)/net/patricia/%.c
--- a/usr/src/uts/common/conf/param.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/conf/param.c	Fri Oct 20 16:37:58 2006 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * 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.
--- a/usr/src/uts/common/inet/Makefile	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -29,11 +29,12 @@
 # include global definitions
 include ../../../Makefile.master
 
-HDRS=	arp.h common.h ipclassifier.h ip.h ip6.h ipdrop.h ipsecah.h ipsecesp.h \
-	ipsec_info.h ip6_asp.h ip_if.h ip_ire.h ip_multi.h ip_ndp.h ip_rts.h \
-	ipsec_impl.h keysock.h led.h mi.h mib2.h nd.h optcom.h sadb.h \
-	sctp_itf.h snmpcom.h tcp.h tcp_sack.h tun.h udp_impl.h arp_impl.h \
-	rawip_impl.h ipp_common.h ip_ftable.h ip_impl.h tcp_impl.h wifi_ioctl.h
+HDRS=	arp.h arp_impl.h common.h ipclassifier.h ip.h ip6.h ipdrop.h ipsecah.h \
+	ipsecesp.h ipsec_info.h ip6_asp.h ip_if.h ip_ire.h ip_multi.h \
+	ip_netinfo.h ip_ndp.h ip_rts.h ipsec_impl.h keysock.h led.h mi.h \
+	mib2.h nd.h optcom.h sadb.h sctp_itf.h snmpcom.h tcp.h tcp_sack.h \
+	tun.h udp_impl.h rawip_impl.h ipp_common.h ip_ftable.h ip_impl.h \
+	tcp_impl.h wifi_ioctl.h
 
 ROOTDIRS= $(ROOT)/usr/include/inet
 
--- a/usr/src/uts/common/inet/arp/arp.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/arp/arp.c	Fri Oct 20 16:37:58 2006 -0700
@@ -41,6 +41,7 @@
 #include <sys/ddi.h>
 #include <sys/sunddi.h>
 #include <sys/cmn_err.h>
+#include <sys/sdt.h>
 #include <sys/vtrace.h>
 #include <sys/strsun.h>
 #include <sys/policy.h>
@@ -48,6 +49,7 @@
 #include <sys/zone.h>
 #include <sys/random.h>
 #include <sys/sdt.h>
+#include <sys/hook_event.h>
 
 #include <inet/common.h>
 #include <inet/optcom.h>
@@ -304,7 +306,17 @@
 
 static void	*ar_g_head;	/* AR Instance Data List Head */
 static caddr_t	ar_g_nd;	/* AR Named Dispatch Head */
-static arl_t	*arl_g_head;	/* ARL List Head */
+
+/*
+ * With the introduction of netinfo (neti kernel module), it is now possible
+ * to access data structures in the ARP module without the code being
+ * executed in the context of the IP module, thus there is no locking being
+ * enforced through the use of STREAMS.
+ *
+ *
+ */
+krwlock_t	arl_g_lock;
+arl_t		*arl_g_head;	/* ARL List Head */
 
 /*
  * TODO: we need a better mechanism to set the ARP hardware type since
@@ -326,6 +338,9 @@
 
 static ace_t	*ar_ce_mask_entries;	/* proto_mask not all ones */
 
+static uint32_t	arp_index_counter = 1;
+static uint32_t	arp_counter_wrapped = 0;
+
 /*
  * Note that all routines which need to queue the message for later
  * processing have to be ioctl_aware to be able to queue the complete message.
@@ -953,17 +968,20 @@
 ar_close(queue_t *q)
 {
 	ar_t	*ar = (ar_t *)q->q_ptr;
+	char	name[LIFNAMSIZ];
 	arl_t	*arl;
 	arl_t	**arlp;
 	cred_t	*cr;
 	arc_t	*arc;
 	mblk_t	*mp1;
+	int	index;
 
 	TRACE_1(TR_FAC_ARP, TR_ARP_CLOSE,
 	    "arp_close: q %p", q);
 
 	arl = ar->ar_arl;
 	if (arl == NULL) {
+		index = 0;
 		/*
 		 * If this is the <ARP-IP-Driver> stream send down
 		 * a closing message to IP and wait for IP to send
@@ -992,6 +1010,8 @@
 		 */
 		ar_ll_cleanup_arl_queue(q);
 	} else {
+		index = arl->arl_index;
+		(void) strcpy(name, arl->arl_name);
 		arl->arl_closing = 1;
 		while (arl->arl_queue != NULL)
 			qwait(arl->arl_rq);
@@ -1010,16 +1030,19 @@
 		ar_ce_walk(ar_ce_delete_per_arl, arl);
 		/* Free any messages waiting for a bind_ack */
 		/* Get the arl out of the chain. */
-		for (arlp = &arl_g_head; arlp[0]; arlp = &arlp[0]->arl_next) {
-			if (arlp[0] == arl) {
-				arlp[0] = arl->arl_next;
+		rw_enter(&arl_g_lock, RW_WRITER);
+		for (arlp = &arl_g_head; *arlp; arlp = &(*arlp)->arl_next) {
+			if (*arlp == arl) {
+				*arlp = arl->arl_next;
 				break;
 			}
 		}
 
 		ASSERT(arl->arl_dlpi_deferred == NULL);
+		ar->ar_arl = NULL;
+		rw_exit(&arl_g_lock);
+
 		mi_free((char *)arl);
-		ar->ar_arl = NULL;
 	}
 	/* Let's break the association between an ARL and IP instance */
 	if (ar->ar_arl_ip_assoc != NULL) {
@@ -1034,6 +1057,17 @@
 	ar_cleanup();
 	qprocsoff(q);
 	crfree(cr);
+
+	if (index != 0) {
+		hook_nic_event_t info;
+
+		info.hne_nic = index;
+		info.hne_lif = 0;
+		info.hne_event = NE_UNPLUMB;
+		info.hne_data = name;
+		info.hne_datalen = strlen(name);
+		(void) hook_run(arpnicevents, (hook_data_t)&info);
+	}
 	return (0);
 }
 
@@ -2116,8 +2150,9 @@
 	arl_t	*arl;
 
 	for (arl = arl_g_head; arl; arl = arl->arl_next) {
-		if (strcmp(arl->arl_name, name) == 0)
+		if (strcmp(arl->arl_name, name) == 0) {
 			return (arl);
+		}
 	}
 	return (NULL);
 }
@@ -2158,6 +2193,43 @@
 	arl->arl_link_up = B_TRUE;
 
 	ar->ar_arl = arl;
+
+	/*
+	 * If/when ARP gets pushed into the IP module then this code to make
+	 * a number uniquely identify an ARP instance can be removed and the
+	 * ifindex from IP used.  Rather than try and reinvent or copy the
+	 * code used by IP for the purpose of allocating an index number
+	 * (and trying to keep the number small), just allocate it in an
+	 * ever increasing manner.  This index number isn't ever exposed to
+	 * users directly, its only use is for providing the pfhooks interface
+	 * with a number it can use to uniquely identify an interface in time.
+	 *
+	 * Using a 32bit counter, over 136 plumbs would need to be done every
+	 * second of every day (non-leap year) for it to wrap around and the
+	 * for() loop below to kick in as a performance concern.
+	 */
+	if (arp_counter_wrapped) {
+		arl_t *as;
+
+		do {
+			for (as = arl_g_head; as != NULL; as = as->arl_next)
+				if (as->arl_index == arp_index_counter) {
+					arp_index_counter++;
+					if (arp_index_counter == 0) {
+						arp_counter_wrapped++;
+						arp_index_counter = 1;
+					}
+					break;
+			}
+		} while (as != NULL);
+	} else {
+		arl->arl_index = arp_index_counter;
+	}
+	arp_index_counter++;
+	if (arp_index_counter == 0) {
+		arp_counter_wrapped++;
+		arp_index_counter = 1;
+	}
 }
 
 /*
@@ -2527,6 +2599,7 @@
 		ar_cleanup();
 		return (err);
 	}
+
 	/*
 	 * We are D_MTPERMOD so it is safe to do qprocson before
 	 * the instance data has been initialized.
@@ -3137,6 +3210,18 @@
 	 * We should check here, but don't.
 	 */
 	DTRACE_PROBE2(rput_normal, arl_t *, arl, arh_t *, arh);
+
+	DTRACE_PROBE3(arp__physical__in__start,
+	    arl_t *, arl, arh_t *, arh, mblk_t *, mp);
+    
+	ARP_HOOK_IN(arp_physical_in_event, arp_physical_in,
+		    arl->arl_index, arh, mp, mp1);
+
+	DTRACE_PROBE1(arp__physical__in__end, mblk_t *, mp);
+
+	if (mp == NULL)
+		return;
+
 	proto = (uint32_t)BE16_TO_U16(arh->arh_proto);
 	src_haddr = (uchar_t *)arh;
 	src_haddr = &src_haddr[ARH_FIXED_LEN];
@@ -3511,6 +3596,7 @@
 	arl_t *old_arl;
 	mblk_t *ioccpy;
 	struct iocblk *iocp;
+	hook_nic_event_t info;
 
 	if (ar->ar_on_ill_stream) {
 		/*
@@ -3572,7 +3658,23 @@
 
 	/* The ppa is sent down by ifconfig */
 	arl->arl_ppa = lifr->lifr_ppa;
+
+	/* 
+	 * A network device is not considered to be fully plumb'd until
+	 * its name has been set using SIOCSLIFNAME.  Once it has 
+	 * been set, it cannot be set again (see code above), so there
+	 * is currently no danger in this function causing two NE_PLUMB
+	 * events without an intervening NE_UNPLUMB.
+	 */
+	info.hne_nic = arl->arl_index;
+	info.hne_lif = 0;
+	info.hne_event = NE_PLUMB;
+	info.hne_data = arl->arl_name;
+	info.hne_datalen = strlen(arl->arl_name);
+	(void) hook_run(arpnicevents, (hook_data_t)&info);
+
 	/* Chain in the new arl. */
+	rw_enter(&arl_g_lock, RW_WRITER);
 	arl->arl_next = arl_g_head;
 	arl_g_head = arl;
 	DTRACE_PROBE1(slifname_set, arl_t *, arl);
@@ -3588,6 +3690,8 @@
 	iocp->ioc_count = msgsize(ioccpy->b_cont);
 	ioccpy->b_wptr = (uchar_t *)(iocp + 1);
 	putnext(arl->arl_wq, ioccpy);
+	rw_exit(&arl_g_lock);
+
 	return (0);
 }
 
@@ -3648,8 +3752,11 @@
 	arl->arl_ppa = ppa;
 	DTRACE_PROBE1(setppa_done, arl_t *, arl);
 	/* Chain in the new arl. */
+	rw_enter(&arl_g_lock, RW_WRITER);
 	arl->arl_next = arl_g_head;
 	arl_g_head = arl;
+	rw_exit(&arl_g_lock);
+
 	return (0);
 }
 
@@ -4355,6 +4462,18 @@
 	bcopy(paddr2, cp, plen);
 	cp += plen;
 	mp->b_cont->b_wptr = cp;
+
+	DTRACE_PROBE3(arp__physical__out__start,
+	    arl_t *, arl, arh_t *, arh, mblk_t *, mp);
+
+	ARP_HOOK_OUT(arp_physical_out_event, arp_physical_out,
+	    arl->arl_index, arh, mp, mp->b_cont);
+
+	DTRACE_PROBE1(arp__physical__out__end, mblk_t *, mp);
+
+	if (mp == NULL)
+		return;
+
 	/* Ship it out. */
 	if (canputnext(arl->arl_wq))
 		putnext(arl->arl_wq, mp);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/inet/arp/arp_netinfo.c	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,338 @@
+/*
+ * 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 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/cmn_err.h>
+#include <sys/stream.h>
+#include <sys/sunddi.h>
+#include <sys/hook.h>
+#include <sys/hook_impl.h>
+#include <net/if.h>
+
+#include <sys/neti.h>
+#include <sys/hook_event.h>
+#include <inet/arp_impl.h>
+
+/*
+ * ARP netinfo entry point declarations.
+ */
+static int 	arp_getifname(phy_if_t, char *, const size_t);
+static int 	arp_getmtu(phy_if_t, lif_if_t);
+static int 	arp_getpmtuenabled(void);
+static int 	arp_getlifaddr(phy_if_t, lif_if_t, size_t,
+		    net_ifaddr_t [], void *);
+static phy_if_t arp_phygetnext(phy_if_t);
+static phy_if_t arp_phylookup(const char *);
+static lif_if_t arp_lifgetnext(phy_if_t, lif_if_t);
+static int 	arp_inject(inject_t, net_inject_t *);
+static phy_if_t arp_routeto(struct sockaddr *);
+static int 	arp_ispartialchecksum(mblk_t *);
+static int 	arp_isvalidchecksum(mblk_t *);
+
+static net_info_t arp_netinfo = {
+	NETINFO_VERSION,
+	NHF_ARP,
+	arp_getifname,
+	arp_getmtu,
+	arp_getpmtuenabled,
+	arp_getlifaddr,
+	arp_phygetnext,
+	arp_phylookup,
+	arp_lifgetnext,
+	arp_inject,
+	arp_routeto,
+	arp_ispartialchecksum,
+	arp_isvalidchecksum
+};
+
+static hook_family_t	arproot;
+
+/*
+ * Hooks for ARP
+ */
+
+hook_event_t		arp_physical_in_event;
+hook_event_t		arp_physical_out_event;
+hook_event_t		arp_nic_events;
+
+hook_event_token_t	arp_physical_in;
+hook_event_token_t	arp_physical_out;
+hook_event_token_t	arpnicevents;
+
+net_data_t		arp = NULL;
+
+/*
+ * Register ARP netinfo functions.
+ */
+void
+arp_net_init()
+{
+
+	arp = net_register(&arp_netinfo);
+	ASSERT(arp != NULL);
+}
+
+/*
+ * Unregister ARP netinfo functions.
+ */
+void
+arp_net_destroy()
+{
+
+	(void) net_unregister(arp);
+}
+
+/*
+ * Initialize ARP hook family and events
+ */
+void
+arp_hook_init()
+{
+
+	HOOK_FAMILY_INIT(&arproot, Hn_ARP);
+	if (net_register_family(arp, &arproot) != 0) {
+		cmn_err(CE_NOTE, "arp_hook_init: "
+		    "net_register_family failed for arp");
+	}
+
+	HOOK_EVENT_INIT(&arp_physical_in_event, NH_PHYSICAL_IN);
+	arp_physical_in = net_register_event(arp, &arp_physical_in_event);
+	if (arp_physical_in == NULL) {
+		cmn_err(CE_NOTE, "arp_hook_init: "
+		    "net_register_event failed for arp/physical_in");
+	}
+
+	HOOK_EVENT_INIT(&arp_physical_out_event, NH_PHYSICAL_OUT);
+	arp_physical_out = net_register_event(arp, &arp_physical_out_event);
+	if (arp_physical_out == NULL) {
+		cmn_err(CE_NOTE, "arp_hook_init: "
+		    "net_register_event failed for arp/physical_out");
+	}
+
+	HOOK_EVENT_INIT(&arp_nic_events, NH_NIC_EVENTS);
+	arpnicevents = net_register_event(arp, &arp_nic_events);
+	if (arpnicevents == NULL) {
+		cmn_err(CE_NOTE, "arp_hook_init: "
+		    "net_register_event failed for arp/nic_events");
+	}
+}
+
+
+void
+arp_hook_destroy()
+{
+	if (arpnicevents != NULL) {
+		if (net_unregister_event(arp, &arp_nic_events) == 0)
+			arpnicevents = NULL;
+	}
+
+	if (arp_physical_out != NULL) {
+		if (net_unregister_event(arp, &arp_physical_out_event) == 0)
+			arp_physical_out = NULL;
+	}
+
+	if (arp_physical_in != NULL) {
+		if (net_unregister_event(arp, &arp_physical_in_event) == 0)
+			arp_physical_in = NULL;
+	}
+
+	(void) net_unregister_family(arp, &arproot);
+}
+
+
+/*
+ * Determine the name of the lower level interface
+ */
+int
+arp_getifname(phy_if_t phy_ifdata, char *buffer, const size_t buflen)
+{
+	arl_t	*arl;
+
+	ASSERT(buffer != NULL);
+
+	rw_enter(&arl_g_lock, RW_READER);
+	for (arl = arl_g_head; arl != NULL; arl = arl->arl_next) {
+		if (arl->arl_index == phy_ifdata) {
+			(void) strlcpy(buffer, arl->arl_name, buflen);
+			rw_exit(&arl_g_lock);
+			return (0);
+		}
+	}
+	rw_exit(&arl_g_lock);
+
+	return (1);
+}
+
+
+/*
+ * Unsupported with ARP.
+ */
+/*ARGSUSED*/
+int
+arp_getmtu(phy_if_t phy_ifdata, lif_if_t ifdata)
+{
+
+	return (-1);
+}
+
+
+/*
+ * Unsupported with ARP.
+ */
+/*ARGSUSED*/
+int
+arp_getpmtuenabled(void)
+{
+
+	return (-1);
+}
+
+
+/*
+ * Unsupported with ARP.
+ */
+/*ARGSUSED*/
+int
+arp_getlifaddr(phy_if_t phy_ifdata, lif_if_t ifdata, size_t nelem,
+	net_ifaddr_t type[], void *storage)
+{
+
+	return (-1);
+}
+
+
+/*
+ * Determine the instance number of the next lower level interface
+ */
+phy_if_t
+arp_phygetnext(phy_if_t phy_ifdata)
+{
+	arl_t *arl;
+	int index;
+
+	rw_enter(&arl_g_lock, RW_READER);
+	if (phy_ifdata == 0) {
+		arl = arl_g_head;
+	} else {
+		for (arl = arl_g_head; arl != NULL; arl = arl->arl_next) {
+			if (arl->arl_index == phy_ifdata) {
+				arl = arl->arl_next;
+				break;
+			}
+		}
+	}
+
+	index = (arl != NULL) ? arl->arl_index : 0;
+
+	rw_exit(&arl_g_lock);
+
+	return (index);
+}
+
+
+/*
+ * Given a network interface name, find its ARP layer instance number.
+ */
+phy_if_t
+arp_phylookup(const char *name)
+{
+	arl_t *arl;
+	int index;
+
+	ASSERT(name != NULL);
+
+	index = 0;
+
+	rw_enter(&arl_g_lock, RW_READER);
+	for (arl = arl_g_head; arl != NULL; arl = arl->arl_next) {
+		if (strcmp(name, arl->arl_name) == 0) {
+			index = arl->arl_index;
+			break;
+		}
+	}
+	rw_exit(&arl_g_lock);
+
+	return (index);
+
+}
+
+
+/*
+ * Unsupported with ARP.
+ */
+/*ARGSUSED*/
+lif_if_t
+arp_lifgetnext(phy_if_t ifp, lif_if_t lif)
+{
+	return (lif_if_t)(-1);
+}
+
+
+/*
+ * Unsupported with ARP.
+ */
+/*ARGSUSED*/
+int
+arp_inject(inject_t injection, net_inject_t *neti)
+{
+	return (-1);
+}
+
+
+/*
+ * Unsupported with ARP.
+ */
+/*ARGSUSED*/
+phy_if_t
+arp_routeto(struct sockaddr *addr)
+{
+	return (phy_if_t)(-1);
+}
+
+
+/*
+ * Unsupported with ARP.
+ */
+/*ARGSUSED*/
+int
+arp_ispartialchecksum(mblk_t *mb)
+{
+	return (-1);
+}
+
+
+/*
+ * Unsupported with ARP.
+ */
+/*ARGSUSED*/
+int
+arp_isvalidchecksum(mblk_t *mb)
+{
+	return (-1);
+}
--- a/usr/src/uts/common/inet/arp/arpddi.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/arp/arpddi.c	Fri Oct 20 16:37:58 2006 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 1992-2002 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 /* Copyright (c) 1990 Mentat Inc. */
@@ -30,8 +29,10 @@
 #include <sys/types.h>
 #include <sys/conf.h>
 #include <sys/modctl.h>
+#include <sys/ksynch.h>
 #include <inet/common.h>
 #include <inet/ip.h>
+#include <inet/arp_impl.h>
 
 #define	INET_NAME	"arp"
 #define	INET_MODDESC	"ARP STREAMS module %I%"
@@ -41,19 +42,34 @@
 #define	INET_DEVMTFLAGS	IP_DEVMTFLAGS	/* since as a driver we're ip */
 #define	INET_MODMTFLAGS	(D_MP | D_MTPERMOD)
 
+static void	arp_ddi_destroy();
+static void	arp_ddi_init();
+
 #include "../inetddi.c"
 
 int
 _init(void)
 {
+	int error;
+
+	arp_ddi_init();
 	INET_BECOME_IP();
-	return (mod_install(&modlinkage));
+
+	error = mod_install(&modlinkage);
+	if (error != 0)
+		arp_ddi_destroy();
+	return error;
 }
 
 int
 _fini(void)
 {
-	return (mod_remove(&modlinkage));
+	int error;
+
+	error = mod_remove(&modlinkage);
+	if (error == 0)
+		arp_ddi_destroy();
+	return error;
 }
 
 int
@@ -61,3 +77,21 @@
 {
 	return (mod_info(&modlinkage, modinfop));
 }
+
+
+static void
+arp_ddi_init()
+{
+	rw_init(&arl_g_lock, "ARP ARl lock", RW_DRIVER, NULL);
+	arp_net_init();
+	arp_hook_init();
+}
+
+
+static void
+arp_ddi_destroy()
+{
+	arp_hook_destroy();
+	arp_net_destroy();
+	rw_destroy(&arl_g_lock);
+}
--- a/usr/src/uts/common/inet/arp_impl.h	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/arp_impl.h	Fri Oct 20 16:37:58 2006 -0700
@@ -72,8 +72,12 @@
 			arl_closing : 1,	/* stream is closing */
 			arl_notifies : 1,	/* handles DL_NOTE_LINK */
 			arl_link_up : 1;	/* DL_NOTE status */
+	uint32_t	arl_index;		/* instance number */
 } arl_t;
 
+extern arl_t		*arl_g_head; 		/* ARL chain head */
+extern krwlock_t	arl_g_lock;
+
 #define	ARL_F_NOARP	0x01
 
 #define	ARL_S_DOWN	0x00
@@ -113,6 +117,74 @@
 	int		ace_xmit_count;
 } ace_t;
 
+/* 
+ * Hooks structures used inside of arp
+ */
+extern hook_event_token_t	arp_physical_in;
+extern hook_event_token_t	arp_physical_out;
+extern hook_event_token_t	arpnicevents;
+
+extern hook_event_t	arp_physical_in_event;
+extern hook_event_t	arp_physical_out_event;
+extern hook_event_t	arp_nic_events;
+
+#define ARPHOOK_INTERESTED_PHYSICAL_IN	\
+	(arp_physical_in_event.he_interested)
+#define ARPHOOK_INTERESTED_PHYSICAL_OUT	\
+	(arp_physical_out_event.he_interested)
+
+#define ARP_HOOK_IN(_hook, _event, _ilp, _hdr, _fm, _m)	\
+								\
+	if ((_hook).he_interested) {                       	\
+		hook_pkt_event_t info;                          \
+								\
+		info.hpe_ifp = _ilp;                       	\
+		info.hpe_ofp = 0;                       	\
+		info.hpe_hdr = _hdr;                            \
+		info.hpe_mp = &(_fm);                           \
+		info.hpe_mb = _m;                               \
+		if (hook_run(_event, (hook_data_t)&info) != 0) {\
+			if (_fm != NULL) {                      \
+				freemsg(_fm);                   \
+				_fm = NULL;                     \
+			}                                       \
+			_hdr = NULL;                            \
+			_m = NULL;                              \
+		} else {                                        \
+			_hdr = info.hpe_hdr;                    \
+			_m = info.hpe_mb;                       \
+		}                                               \
+	}
+
+#define ARP_HOOK_OUT(_hook, _event, _olp, _hdr, _fm, _m)	\
+								\
+	if ((_hook).he_interested) {                       	\
+		hook_pkt_event_t info;                          \
+								\
+		info.hpe_ifp = 0;                       	\
+		info.hpe_ofp = _olp;                       	\
+		info.hpe_hdr = _hdr;                            \
+		info.hpe_mp = &(_fm);                           \
+		info.hpe_mb = _m;                               \
+		if (hook_run(_event,                            \
+		    (hook_data_t)&info) != 0) {                 \
+			if (_fm != NULL) {                      \
+				freemsg(_fm);                   \
+				_fm = NULL;                     \
+			}                                       \
+			_hdr = NULL;                            \
+			_m = NULL;                              \
+		} else {                                        \
+			_hdr = info.hpe_hdr;                    \
+			_m = info.hpe_mb;                       \
+		}                                               \
+	}
+
+extern void	arp_hook_init();
+extern void	arp_hook_destroy();
+extern void	arp_net_init();
+extern void	arp_net_destroy();
+
 #endif	/* _KERNEL */
 
 #ifdef	__cplusplus
--- a/usr/src/uts/common/inet/ip.h	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ip.h	Fri Oct 20 16:37:58 2006 -0700
@@ -43,6 +43,10 @@
 #include <net/if.h>
 #include <netinet/ip.h>
 #include <netinet/igmp.h>
+#include <sys/neti.h>
+#include <sys/hook.h>
+#include <sys/hook_event.h>
+#include <sys/hook_impl.h>
 
 #ifdef _KERNEL
 #include <netinet/ip6.h>
@@ -1832,6 +1836,11 @@
 	int	ill_ip_muxid;		/* muxid returned from plink for ip */
 
 	/*
+	 * NIC event information attached, to be used by nic event hooks.
+	 */
+	hook_nic_event_t	*ill_nic_event_info;
+
+	/*
 	 * Used for IP frag reassembly throttling on a per ILL basis.
 	 *
 	 * Note: frag_count is approximate, its added to and subtracted from
@@ -2917,6 +2926,145 @@
 extern uint_t	loopback_packets;
 
 /*
+ * Hooks structures used inside of ip
+ */
+extern hook_event_token_t	ipv4firewall_physical_in;
+extern hook_event_token_t	ipv4firewall_physical_out;
+extern hook_event_token_t	ipv4firewall_forwarding;
+extern hook_event_token_t	ipv4firewall_loopback_in;
+extern hook_event_token_t	ipv4firewall_loopback_out;
+extern hook_event_token_t	ipv4nicevents;
+
+extern hook_event_token_t	ipv6firewall_physical_in;
+extern hook_event_token_t	ipv6firewall_physical_out;
+extern hook_event_token_t	ipv6firewall_forwarding;
+extern hook_event_token_t	ipv6firewall_loopback_in;
+extern hook_event_token_t	ipv6firewall_loopback_out;
+extern hook_event_token_t	ipv6nicevents;
+
+extern hook_event_t	ip4_physical_in_event;
+extern hook_event_t	ip4_physical_out_event;
+extern hook_event_t	ip4_forwarding_event;
+extern hook_event_t	ip4_loopback_in_event;
+extern hook_event_t	ip4_loopback_out_event;
+extern hook_event_t	ip4_nic_events;
+
+extern hook_event_t	ip6_physical_in_event;
+extern hook_event_t	ip6_physical_out_event;
+extern hook_event_t	ip6_forwarding_event;
+extern hook_event_t	ip6_loopback_in_event;
+extern hook_event_t	ip6_loopback_out_event;
+extern hook_event_t	ip6_nic_events;
+
+#define	HOOKS4_INTERESTED_PHYSICAL_IN	\
+	(ip4_physical_in_event.he_interested)
+#define	HOOKS6_INTERESTED_PHYSICAL_IN	\
+	(ip6_physical_in_event.he_interested)
+#define	HOOKS4_INTERESTED_PHYSICAL_OUT	\
+	(ip4_physical_out_event.he_interested)
+#define	HOOKS6_INTERESTED_PHYSICAL_OUT	\
+	(ip6_physical_out_event.he_interested)
+#define	HOOKS4_INTERESTED_FORWARDING	\
+	(ip4_forwarding_event.he_interested)
+#define	HOOKS6_INTERESTED_FORWARDING	\
+	(ip6_forwarding_event.he_interested)
+#define	HOOKS4_INTERESTED_LOOPBACK_IN	\
+	(ip4_loopback_in_event.he_interested)
+#define	HOOKS6_INTERESTED_LOOPBACK_IN	\
+	(ip6_loopback_in_event.he_interested)
+#define	HOOKS4_INTERESTED_LOOPBACK_OUT	\
+	(ip4_loopback_out_event.he_interested)
+#define	HOOKS6_INTERESTED_LOOPBACK_OUT	\
+	(ip6_loopback_out_event.he_interested)
+
+/*
+ * Hooks marcos used inside of ip
+ */
+#define	IPHA_VHL	ipha_version_and_hdr_length
+
+#define	FW_HOOKS(_hook, _event, _flag, _ilp, _olp, _iph, _fm, _m)	\
+									\
+	if ((_hook).he_interested) {	\
+		hook_pkt_event_t info;					\
+									\
+		_NOTE(CONSTCOND)					\
+		ASSERT((_ilp != NULL) || (_olp != NULL));		\
+									\
+		_NOTE(CONSTCOND)					\
+		if ((_ilp != NULL) &&					\
+		    (((ill_t *)(_ilp))->ill_phyint != NULL))		\
+			info.hpe_ifp = (phy_if_t)((ill_t *)		\
+			    (_ilp))->ill_phyint->phyint_ifindex;	\
+		else							\
+			info.hpe_ifp = 0;				\
+									\
+		_NOTE(CONSTCOND)					\
+		if ((_olp != NULL) &&					\
+		    (((ill_t *)(_olp))->ill_phyint != NULL))		\
+			info.hpe_ofp = (phy_if_t)((ill_t *)		\
+			    (_olp))->ill_phyint->phyint_ifindex;	\
+		else							\
+			info.hpe_ofp = 0;				\
+		info.hpe_hdr = _iph;					\
+		info.hpe_mp = &(_fm);					\
+		info.hpe_mb = _m;					\
+		if (hook_run(_event, (hook_data_t)&info) != 0) {	\
+			ip2dbg(("%s hook dropped mblk chain %p hdr %p\n",\
+			    (_hook).he_name, (void *)_fm, (void *)_m));	\
+			if (_fm != NULL) {				\
+				freemsg(_fm);				\
+				_fm = NULL;				\
+			}						\
+			_iph = NULL;					\
+			_m = NULL;					\
+		} else {						\
+			_iph = info.hpe_hdr;				\
+			_m = info.hpe_mb;				\
+		}							\
+	}
+
+#define	FW_HOOKS6(_hook, _event, _flag, _ilp, _olp, _iph, _fm, _m)	\
+									\
+	if ((_hook).he_interested) {	\
+		hook_pkt_event_t info;					\
+									\
+		_NOTE(CONSTCOND)					\
+		ASSERT((_ilp != NULL) || (_olp != NULL));		\
+									\
+		_NOTE(CONSTCOND)					\
+		if ((_ilp != NULL) &&					\
+		    (((ill_t *)(_ilp))->ill_phyint != NULL))		\
+			info.hpe_ifp = (phy_if_t)((ill_t *)		\
+			    (_ilp))->ill_phyint->phyint_ifindex;	\
+		else							\
+			info.hpe_ifp = 0;				\
+									\
+		_NOTE(CONSTCOND)					\
+		if ((_olp != NULL) &&					\
+		    (((ill_t *)(_olp))->ill_phyint != NULL))		\
+			info.hpe_ofp = (phy_if_t)((ill_t *)		\
+			    (_olp))->ill_phyint->phyint_ifindex;	\
+		else							\
+			info.hpe_ofp = 0;				\
+		info.hpe_hdr = _iph;					\
+		info.hpe_mp = &(_fm);					\
+		info.hpe_mb = _m;					\
+		if (hook_run(_event, (hook_data_t)&info) != 0) {	\
+			ip2dbg(("%s hook dropped mblk chain %p hdr %p\n",\
+			    (_hook).he_name, (void *)_fm, (void *)_m));	\
+			if (_fm != NULL) {				\
+				freemsg(_fm);				\
+				_fm = NULL;				\
+			}						\
+			_iph = NULL;					\
+			_m = NULL;					\
+		} else {						\
+			_iph = info.hpe_hdr;				\
+			_m = info.hpe_mb;				\
+		}							\
+	}
+
+/*
  * Network byte order macros
  */
 #ifdef	_BIG_ENDIAN
@@ -3049,6 +3197,9 @@
 extern struct qinit rinit_acceptor_tcp;
 extern struct qinit winit_acceptor_tcp;
 
+extern net_data_t ipv4;
+extern net_data_t ipv6;
+
 extern void	conn_drain_insert(conn_t *connp);
 extern	int	conn_ipsec_length(conn_t *connp);
 extern void	ip_wput_ipsec_out(queue_t *, mblk_t *, ipha_t *, ill_t *,
--- a/usr/src/uts/common/inet/ip/ip.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ip/ip.c	Fri Oct 20 16:37:58 2006 -0700
@@ -51,6 +51,7 @@
 #include <sys/systm.h>
 #include <sys/param.h>
 #include <sys/kmem.h>
+#include <sys/sdt.h>
 #include <sys/socket.h>
 #include <sys/vtrace.h>
 #include <sys/isa_defs.h>
@@ -99,6 +100,7 @@
 #include <sys/iphada.h>
 #include <inet/tun.h>
 #include <inet/ipdrop.h>
+#include <inet/ip_netinfo.h>
 
 #include <sys/ethernet.h>
 #include <net/if_types.h>
@@ -115,6 +117,7 @@
 #include <inet/sctp_ip.h>
 #include <inet/sctp/sctp_impl.h>
 #include <inet/udp_impl.h>
+#include <sys/sunddi.h>
 
 #include <sys/tsol/label.h>
 #include <sys/tsol/tnet.h>
@@ -1469,6 +1472,9 @@
 /* Defined in ip_if.c, protect the list of IPsec capable ills */
 extern krwlock_t ipsec_capab_ills_lock;
 
+/* Defined in ip_netinfo.c */
+extern ddi_taskq_t	*eventq_queue_nic;
+
 /* Packet dropper for IP IPsec processing failures */
 ipdropper_t ip_dropper;
 
@@ -5338,6 +5344,7 @@
 	ipsq_t	*ipsq;
 	ipif_t	*ipif;
 	queue_t	*q = ill->ill_rq;
+	hook_nic_event_t *info;
 
 	/*
 	 * Forcibly enter the ipsq after some delay. This is to take
@@ -5436,6 +5443,21 @@
 	if (ill->ill_credp != NULL)
 		crfree(ill->ill_credp);
 
+	/*
+	 * Unhook the nic event message from the ill and enqueue it into the nic
+	 * event taskq.
+	 */
+	if ((info = ill->ill_nic_event_info) != NULL) {
+		if (ddi_taskq_dispatch(eventq_queue_nic, ip_ne_queue_func,
+		    (void *)info, DDI_SLEEP) == DDI_FAILURE) {
+			ip2dbg(("ip_ioctl_finish:ddi_taskq_dispatch failed\n"));
+			if (info->hne_data != NULL)
+				kmem_free(info->hne_data, info->hne_datalen);
+			kmem_free(info, sizeof (hook_nic_event_t));
+		}
+		ill->ill_nic_event_info = NULL;
+	}
+
 	mi_close_free((IDP)ill);
 	q->q_ptr = WR(q)->q_ptr = NULL;
 
@@ -5701,6 +5723,10 @@
 void
 ip_ddi_destroy(void)
 {
+	ipv4_hook_destroy();
+	ipv6_hook_destroy();
+	ip_net_destroy();
+
 	tnet_fini();
 	tcp_ddi_destroy();
 	sctp_ddi_destroy();
@@ -5794,6 +5820,10 @@
 	icmp_kstat_init();
 	ipsec_loader_start();
 	tnet_init();
+
+	ip_net_init();
+	ipv4_hook_init();
+	ipv6_hook_init();
 }
 
 /*
@@ -7200,6 +7230,7 @@
 	mblk_t		*first_mp;
 	uint32_t	ill_index;
 	ipxmit_state_t	pktxmit_state;
+	ill_t		*out_ill;
 
 	ASSERT(ire != NULL);
 	ASSERT(ire->ire_ipif->ipif_net_type == IRE_IF_NORESOLVER);
@@ -7259,6 +7290,26 @@
 	ill_index = ire->ire_ipif->ipif_ill->ill_phyint->phyint_ifindex;
 
 	/*
+	 * This location is chosen for the placement of the forwarding hook
+	 * because at this point we know that we have a path out for the
+	 * packet but haven't yet applied any logic (such as fragmenting)
+	 * that happen as part of transmitting the packet out.
+	 */
+	out_ill = ire->ire_ipif->ipif_ill;
+
+	DTRACE_PROBE4(ip4__forwarding__start,
+	    ill_t *, in_ill, ill_t *, out_ill, ipha_t *, ipha, mblk_t *, mp);
+
+	FW_HOOKS(ip4_forwarding_event, ipv4firewall_forwarding,
+	    MSG_FWCOOKED_FORWARD, in_ill, out_ill, ipha, mp, mp);
+
+	DTRACE_PROBE1(ip4__forwarding__end, mblk_t *, mp);
+
+	if (mp == NULL)
+		return;
+	pkt_len = ntohs(ipha->ipha_length);
+
+	/*
 	 * ip_mrtun_forward is only used by foreign agent to reverse
 	 * tunnel the incoming packet. So it does not do any option
 	 * processing for source routing.
@@ -7302,6 +7353,14 @@
 
 	ASSERT(ire->ire_ipif != NULL);
 
+	DTRACE_PROBE4(ip4__physical__out__start, ill_t *, NULL,
+	    ill_t *, ire->ire_ipif->ipif_ill, ipha_t *, ipha, mblk_t *, mp);
+	FW_HOOKS(ip4_physical_out_event, ipv4firewall_physical_out,
+	    MSG_FWCOOKED_OUT, NULL, out_ill, ipha, mp, mp);
+	DTRACE_PROBE1(ip4__physical__out__end, mblk_t *, mp);
+	if (mp == NULL)
+		return;
+
 	/* Now send the packet to the tunnel interface */
 	mp->b_prev = SET_BPREV_FLAG(IPP_FWD_OUT);
 	q = ire->ire_stq;
@@ -13523,14 +13582,6 @@
 	return (B_FALSE);
 }
 
-#define	SEND_PKT(ire, mp)			\
-{						\
-	UPDATE_IB_PKT_COUNT(ire);		\
-	(ire)->ire_last_used_time = lbolt;	\
-	BUMP_MIB(&ip_mib, ipForwDatagrams);	\
-	putnext((ire)->ire_stq, mp);		\
-}
-
 ire_t *
 ip_fast_forward(ire_t *ire, ipaddr_t dst,  ill_t *ill, mblk_t *mp)
 {
@@ -13616,6 +13667,17 @@
 		return (ire);
 	}
 
+	DTRACE_PROBE4(ip4__forwarding__start,
+	    ill_t *, ill, ill_t *, stq_ill, ipha_t *, ipha, mblk_t *, mp);
+
+	FW_HOOKS(ip4_forwarding_event, ipv4firewall_forwarding,
+	    MSG_FWCOOKED_FORWARD, ill, stq_ill, ipha, mp, mp);
+
+	DTRACE_PROBE1(ip4__forwarding__end, mblk_t *, mp);
+
+	if (mp == NULL)
+		goto drop;
+
 	mp->b_datap->db_struioun.cksum.flags = 0;
 	/* Adjust the checksum to reflect the ttl decrement. */
 	sum = (int)ipha->ipha_hdr_checksum + IP_HDR_CSUM_TTL_ADJUST;
@@ -13632,9 +13694,25 @@
 	    MBLKL(ire->ire_nce->nce_fp_mp) : 0;
 
 	if (hlen != 0 || ire->ire_nce->nce_res_mp != NULL) {
-		mp = ip_wput_attach_llhdr(mp, ire, 0, 0);
+		mblk_t *mpip = mp;
+
+		mp = ip_wput_attach_llhdr(mpip, ire, 0, 0);
 		if (mp != NULL) {
-			SEND_PKT(ire, mp);
+			DTRACE_PROBE4(ip4__physical__out__start,
+			    ill_t *, NULL, ill_t *, stq_ill,
+			    ipha_t *, ipha, mblk_t *, mp);
+			FW_HOOKS(ip4_physical_out_event,
+			    ipv4firewall_physical_out, MSG_FWCOOKED_OUT, NULL,
+			    stq_ill, ipha, mp, mpip);
+			DTRACE_PROBE1(ip4__physical__out__end, mblk_t *,
+			    mp);
+			if (mp == NULL)
+				goto drop;
+
+			UPDATE_IB_PKT_COUNT(ire);
+			ire->ire_last_used_time = lbolt;
+			BUMP_MIB(&ip_mib, ipForwDatagrams);
+			putnext(ire->ire_stq, mp);
 			return (ire);
 		}
 	}
@@ -14492,6 +14570,30 @@
 			}
 		}
 
+		/*
+		 * The event for packets being received from a 'physical'
+		 * interface is placed before validation of the source and/or
+		 * destination address as being local so that packets such as
+		 * these that are found on the network can be observed via
+		 * this interface.  The checks prior to this have all been
+		 * to do with validating the sanity of the packet - length
+		 * fields vs data in the buffer, buffer size, etc, otherwise
+		 * uninteresting packet flaws that will always lead to them
+		 * being discarded.
+		 */
+		DTRACE_PROBE4(ip4__physical__in__start,
+		    ill_t *, ill, ill_t *, NULL,
+		    ipha_t *, ipha, mblk_t *, first_mp);
+
+		FW_HOOKS(ip4_physical_in_event, ipv4firewall_physical_in,
+		    MSG_FWCOOKED_IN, ill, NULL, ipha, first_mp, mp);
+
+		DTRACE_PROBE1(ip4__physical__in__end, mblk_t *, first_mp);
+
+		if (first_mp == NULL) {
+			continue;
+		}
+
 		/* Obtain the dst of the current packet */
 		dst = ipha->ipha_dst;
 
@@ -14505,6 +14607,26 @@
 		}
 
 		/*
+		 * The event for packets being received from a 'physical'
+		 * interface is placed after validation of the source and/or
+		 * destination address as being local so that packets can be
+		 * redirected to loopback addresses using ipnat.
+		 */
+		DTRACE_PROBE4(ip4__physical__in__start,
+		    ill_t *, ill, ill_t *, NULL,
+		    ipha_t *, ipha, mblk_t *, first_mp);
+
+		FW_HOOKS(ip4_physical_in_event, ipv4firewall_physical_in,
+		    MSG_FWCOOKED_IN, ill, NULL, ipha, first_mp, mp);
+
+		DTRACE_PROBE1(ip4__physical__in__end, mblk_t *, first_mp);
+
+		if (first_mp == NULL) {
+			continue;
+		}
+		dst = ipha->ipha_dst;
+
+		/*
 		 * Attach any necessary label information to
 		 * this packet
 		 */
@@ -15007,6 +15129,7 @@
 	boolean_t	success;
 	boolean_t	ioctl_aborted = B_FALSE;
 	boolean_t	log = B_TRUE;
+	hook_nic_event_t	*info;
 
 	ip1dbg(("ip_rput_dlpi_writer .."));
 	ill = (ill_t *)q->q_ptr;
@@ -15247,7 +15370,33 @@
 		ip1dbg(("ip_rput_dlpi: bind_ack %s\n", ill->ill_name));
 
 		mutex_enter(&ill->ill_lock);
+
 		ill->ill_dl_up = 1;
+
+		if ((info = ill->ill_nic_event_info) != NULL) {
+			ip2dbg(("ip_rput_dlpi_writer: unexpected nic event %d "
+			    "attached for %s\n", info->hne_event,
+			    ill->ill_name));
+			if (info->hne_data != NULL)
+				kmem_free(info->hne_data, info->hne_datalen);
+			kmem_free(info, sizeof (hook_nic_event_t));
+		}
+
+		info = kmem_alloc(sizeof (hook_nic_event_t), KM_NOSLEEP);
+		if (info != NULL) {
+			info->hne_nic = ill->ill_phyint->phyint_ifindex;
+			info->hne_lif = 0;
+			info->hne_event = NE_UP;
+			info->hne_data = NULL;
+			info->hne_datalen = 0;
+			info->hne_family = ill->ill_isv6 ? ipv6 : ipv4;
+		} else
+			ip2dbg(("ip_rput_dlpi_writer: could not attach UP nic "
+			    "event information for %s (ENOMEM)\n",
+			    ill->ill_name));
+
+		ill->ill_nic_event_info = info;
+
 		mutex_exit(&ill->ill_lock);
 
 		/*
@@ -16068,6 +16217,7 @@
 #define	rptr	((uchar_t *)ipha)
 	uint32_t	max_frag;
 	uint32_t	ill_index;
+	ill_t		*out_ill;
 
 	/* Get the ill_index of the incoming ILL */
 	ill_index = (in_ill != NULL) ? in_ill->ill_phyint->phyint_ifindex : 0;
@@ -16122,6 +16272,20 @@
 	/* Get the ill_index of the outgoing ILL */
 	ill_index = ire->ire_ipif->ipif_ill->ill_phyint->phyint_ifindex;
 
+	out_ill = ire->ire_ipif->ipif_ill;
+
+	DTRACE_PROBE4(ip4__forwarding__start,
+	    ill_t *, in_ill, ill_t *, out_ill, ipha_t *, ipha, mblk_t *, mp);
+
+	FW_HOOKS(ip4_forwarding_event, ipv4firewall_forwarding,
+	    MSG_FWCOOKED_FORWARD, in_ill, out_ill, ipha, mp, mp);
+
+	DTRACE_PROBE1(ip4__forwarding__end, mblk_t *, mp);
+
+	if (mp == NULL)
+		return;
+	pkt_len = ntohs(ipha->ipha_length);
+
 	if (is_system_labeled()) {
 		mblk_t *mp1;
 
@@ -16174,6 +16338,15 @@
 		ip2dbg(("ip_rput_forward:sent to ip_wput_frag\n"));
 		return;
 	}
+
+	DTRACE_PROBE4(ip4__physical__out__start, ill_t *, NULL,
+	    ill_t *, ire->ire_ipif->ipif_ill, ipha_t *, ipha, mblk_t *, mp);
+	FW_HOOKS(ip4_physical_out_event, ipv4firewall_physical_out,
+	    MSG_FWCOOKED_OUT, NULL, out_ill, ipha, mp, mp);
+	DTRACE_PROBE1(ip4__physical__out__end, mblk_t *, mp);
+	if (mp == NULL)
+		return;
+
 	mp->b_prev = (mblk_t *)IPP_FWD_OUT;
 	ip1dbg(("ip_rput_forward: Calling ip_xmit_v4\n"));
 	(void) ip_xmit_v4(mp, ire, NULL, B_FALSE);
@@ -21242,6 +21415,7 @@
 	ill_t		*conn_outgoing_ill = NULL;
 	ill_t		*ire_ill;
 	ill_t		*ire1_ill;
+	ill_t		*out_ill;
 	uint32_t 	ill_index = 0;
 	boolean_t	multirt_send = B_FALSE;
 	int		err;
@@ -21772,6 +21946,16 @@
 				multirt_send = B_FALSE;
 			}
 		}
+
+		DTRACE_PROBE4(ip4__physical__out__start, ill_t *, NULL,
+		    ill_t *, ire->ire_ipif->ipif_ill, ipha_t *, ipha,
+		    mblk_t *, mp);
+		FW_HOOKS(ip4_physical_out_event, ipv4firewall_physical_out,
+		    MSG_FWCOOKED_OUT, NULL, ire->ire_ipif->ipif_ill, ipha, mp, mp);
+		DTRACE_PROBE1(ip4__physical__out__end, mblk_t *, mp);
+		if (mp == NULL)
+			goto release_ire_and_ill;
+
 		mp->b_prev = SET_BPREV_FLAG(IPP_LOCAL_OUT);
 		DTRACE_PROBE2(ip__xmit__1, mblk_t *, mp, ire_t *, ire);
 		pktxmit_state = ip_xmit_v4(mp, ire, NULL, B_TRUE);
@@ -21779,6 +21963,7 @@
 		    (pktxmit_state == LLHDR_RESLV_FAILED)) {
 			ip2dbg(("ip_wput_ire: ip_xmit_v4 failed"
 			    "- packet dropped\n"));
+release_ire_and_ill:
 			ire_refrele(ire);
 			if (next_mp != NULL) {
 				freemsg(next_mp);
@@ -22347,6 +22532,20 @@
 					}
 				}
 
+				out_ill = ire->ire_ipif->ipif_ill;
+				DTRACE_PROBE4(ip4__physical__out__start,
+				    ill_t *, NULL,
+				    ill_t *, out_ill,
+				    ipha_t *, ipha, mblk_t *, mp);
+				FW_HOOKS(ip4_physical_out_event,
+				    ipv4firewall_physical_out,
+				    MSG_FWCOOKED_OUT, NULL, out_ill,
+				    ipha, mp, mp);
+				DTRACE_PROBE1(ip4__physical__out__end,
+				    mblk_t *, mp);
+				if (mp == NULL)
+					goto release_ire_and_ill_2;
+
 				ASSERT(ipsec_len == 0);
 				mp->b_prev =
 				    SET_BPREV_FLAG(IPP_LOCAL_OUT);
@@ -22356,6 +22555,7 @@
 				    NULL, B_TRUE);
 				if ((pktxmit_state == SEND_FAILED) ||
 				    (pktxmit_state == LLHDR_RESLV_FAILED)) {
+release_ire_and_ill_2:
 					if (next_mp) {
 						freemsg(next_mp);
 						ire_refrele(ire1);
@@ -22510,18 +22710,54 @@
 		ire->ire_last_used_time = lbolt;
 		ASSERT(ire->ire_ipif != NULL);
 		if (!next_mp) {
+			/*
+			 * Is there an "in" and "out" for traffic local
+			 * to a host (loopback)?  The code in Solaris doesn't
+			 * explicitly draw a line in its code for in vs out,
+			 * so we've had to draw a line in the sand: ip_wput_ire
+			 * is considered to be the "output" side and
+			 * ip_wput_local to be the "input" side.
+			 */
+			out_ill = ire->ire_ipif->ipif_ill;
+
+			DTRACE_PROBE4(ip4__loopback__out__start,
+			    ill_t *, NULL, ill_t *, out_ill,
+			    ipha_t *, ipha, mblk_t *, first_mp);
+
+			FW_HOOKS(ip4_loopback_out_event,
+			    ipv4firewall_loopback_out, MSG_FWCOOKED_OUT,
+			    NULL, out_ill, ipha, first_mp, mp);
+
+			DTRACE_PROBE1(ip4__loopback__out_end,
+			    mblk_t *, first_mp);
+
 			TRACE_2(TR_FAC_IP, TR_IP_WPUT_IRE_END,
 			    "ip_wput_ire_end: q %p (%S)",
 			    q, "local address");
-			ip_wput_local(q, ire->ire_ipif->ipif_ill, ipha,
-			    first_mp, ire, 0, ire->ire_zoneid);
+
+			if (first_mp != NULL)
+				ip_wput_local(q, out_ill, ipha,
+				    first_mp, ire, 0, ire->ire_zoneid);
 			ire_refrele(ire);
 			if (conn_outgoing_ill != NULL)
 				ill_refrele(conn_outgoing_ill);
 			return;
 		}
-		ip_wput_local(q, ire->ire_ipif->ipif_ill, ipha, first_mp,
-		    ire, 0, ire->ire_zoneid);
+
+		out_ill = ire->ire_ipif->ipif_ill;
+
+		DTRACE_PROBE4(ip4__loopback__out__start,
+		    ill_t *, NULL, ill_t *, out_ill,
+		    ipha_t *, ipha, mblk_t *, first_mp);
+
+		FW_HOOKS(ip4_loopback_out_event, ipv4firewall_loopback_out,
+		    MSG_FWCOOKED_OUT, NULL, out_ill, ipha, first_mp, mp);
+
+		DTRACE_PROBE1(ip4__loopback__out__end, mblk_t *, first_mp);
+
+		if (first_mp != NULL)
+			ip_wput_local(q, out_ill, ipha,
+			    first_mp, ire, 0, ire->ire_zoneid);
 	}
 next:
 	/*
@@ -23072,13 +23308,14 @@
 	ipha_t		*ipha;
 	int		ip_data_end;
 	int		len;
-	mblk_t		*mp = mp_orig;
+	mblk_t		*mp = mp_orig, *mp1;
 	int		offset;
 	queue_t		*q;
 	uint32_t	v_hlen_tos_len;
 	mblk_t		*first_mp;
 	boolean_t	mctl_present;
 	ill_t		*ill;
+	ill_t		*out_ill;
 	mblk_t		*xmit_mp;
 	mblk_t		*carve_mp;
 	ire_t		*ire1 = NULL;
@@ -23440,13 +23677,27 @@
 		UNLOCK_IRE_FP_MP(ire);
 		q = ire->ire_stq;
 		BUMP_MIB(&ip_mib, ipFragCreates);
-		putnext(q, xmit_mp);
-		if (pkt_type != OB_PKT) {
-			/*
-			 * Update the packet count of trailing
-			 * RTF_MULTIRT ires.
-			 */
-			UPDATE_OB_PKT_COUNT(ire);
+
+		out_ill = (ill_t *)q->q_ptr;
+
+		DTRACE_PROBE4(ip4__physical__out__start,
+		    ill_t *, NULL, ill_t *, out_ill,
+		    ipha_t *, ipha, mblk_t *, xmit_mp);
+
+		FW_HOOKS(ip4_physical_out_event, ipv4firewall_physical_out,
+		    MSG_FWCOOKED_OUT, NULL, out_ill, ipha, xmit_mp, mp);
+
+		DTRACE_PROBE1(ip4__physical__out__end, mblk_t *, xmit_mp);
+
+		if (xmit_mp != NULL) {
+			putnext(q, xmit_mp);
+			if (pkt_type != OB_PKT) {
+				/*
+				 * Update the packet count of trailing
+				 * RTF_MULTIRT ires.
+				 */
+				UPDATE_OB_PKT_COUNT(ire);
+			}
 		}
 
 		if (multirt_send) {
@@ -23709,14 +23960,36 @@
 			}
 			UNLOCK_IRE_FP_MP(ire);
 			BUMP_MIB(&ip_mib, ipFragCreates);
-			putnext(q, xmit_mp);
-
-			if (pkt_type != OB_PKT) {
-				/*
-				 * Update the packet count of trailing
-				 * RTF_MULTIRT ires.
-				 */
-				UPDATE_OB_PKT_COUNT(ire);
+
+			mp1 = mp;
+			out_ill = (ill_t *)q->q_ptr;
+
+			DTRACE_PROBE4(ip4__physical__out__start,
+			    ill_t *, NULL, ill_t *, out_ill,
+			    ipha_t *, ipha, mblk_t *, xmit_mp);
+
+			FW_HOOKS(ip4_physical_out_event,
+			    ipv4firewall_physical_out, MSG_FWCOOKED_OUT,
+			    NULL, out_ill, ipha, xmit_mp, mp);
+
+			DTRACE_PROBE1(ip4__physical__out__end,
+			    mblk_t *, xmit_mp);
+
+			if (mp != mp1 && hdr_mp == mp1)
+				hdr_mp = mp;
+			if (mp != mp1 && mp_orig == mp1)
+				mp_orig = mp;
+
+			if (xmit_mp != NULL) {
+				putnext(q, xmit_mp);
+
+				if (pkt_type != OB_PKT) {
+					/*
+					 * Update the packet count of trailing
+					 * RTF_MULTIRT ires.
+					 */
+					UPDATE_OB_PKT_COUNT(ire);
+				}
 			}
 
 			/* All done if we just consumed the hdr_mp. */
@@ -23901,6 +24174,18 @@
 		mctl_present = B_FALSE;
 	}
 
+	DTRACE_PROBE4(ip4__loopback__in__start,
+	    ill_t *, ill, ill_t *, NULL,
+	    ipha_t *, ipha, mblk_t *, first_mp);
+
+	FW_HOOKS(ip4_loopback_in_event, ipv4firewall_loopback_in,
+	    MSG_FWCOOKED_IN, ill, NULL, ipha, first_mp, mp);
+
+	DTRACE_PROBE1(ip4__loopback__in__end, mblk_t *, first_mp);
+
+	if (first_mp == NULL)
+		return;
+
 	loopback_packets++;
 
 	ip2dbg(("ip_wput_local: from 0x%x to 0x%x in zone %d\n",
@@ -24447,6 +24732,7 @@
 	zoneid_t zoneid;
 	boolean_t ill_need_rele = B_FALSE;
 	boolean_t ire_need_rele = B_FALSE;
+	ill_t *out_ill;
 
 	mp = ipsec_mp->b_cont;
 	io = (ipsec_out_t *)ipsec_mp->b_rptr;
@@ -24605,8 +24891,23 @@
 	/* Local delivery */
 	if (ire->ire_stq == NULL) {
 		ASSERT(q != NULL);
-		ip_wput_local_v6(RD(q), ire->ire_ipif->ipif_ill, ip6h, ipsec_mp,
-		    ire, 0);
+
+		/* PFHooks: LOOPBACK_OUT */
+		out_ill = ire->ire_ipif->ipif_ill;
+
+		DTRACE_PROBE4(ip6__loopback__out__start,
+		    ill_t *, NULL, ill_t *, out_ill,
+		    ip6_t *, ip6h, mblk_t *, ipsec_mp);
+
+		FW_HOOKS6(ip6_loopback_out_event, ipv6firewall_loopback_out,
+		    MSG_FWCOOKED_OUT, NULL, out_ill, ip6h,
+		    ipsec_mp, mp);
+
+		DTRACE_PROBE1(ip6__loopback__out__end, mblk_t *, ipsec_mp);
+
+		if (ipsec_mp != NULL)
+			ip_wput_local_v6(RD(q), out_ill,
+			    ip6h, ipsec_mp, ire, 0);
 		if (ire_need_rele)
 			ire_refrele(ire);
 		return;
@@ -24734,6 +25035,7 @@
 	uint32_t cksum;
 	uint16_t *up;
 	ipxmit_state_t	pktxmit_state;
+	ill_t	*out_ill;
 #ifdef	_BIG_ENDIAN
 #define	LENGTH	(v_hlen_tos_len & 0xFFFF)
 #else
@@ -24950,8 +25252,22 @@
 		ire->ire_last_used_time = lbolt;
 		if (ipha->ipha_src == 0)
 			ipha->ipha_src = ire->ire_src_addr;
-		ip_wput_local(RD(q), ire->ire_ipif->ipif_ill, ipha, ipsec_mp,
-		    ire, 0, zoneid);
+
+		/* PFHooks: LOOPBACK_OUT */
+		out_ill = ire->ire_ipif->ipif_ill;
+
+		DTRACE_PROBE4(ip4__loopback__out__start,
+		    ill_t *, NULL, ill_t *, out_ill,
+		    ipha_t *, ipha, mblk_t *, ipsec_mp);
+
+		FW_HOOKS(ip4_loopback_out_event, ipv4firewall_loopback_out,
+		    MSG_FWCOOKED_OUT, NULL, out_ill, ipha, ipsec_mp, mp);
+
+		DTRACE_PROBE1(ip4__loopback__out__end, mblk_t *, ipsec_mp);
+
+		if (ipsec_mp != NULL)
+			ip_wput_local(RD(q), out_ill,
+			    ipha, ipsec_mp, ire, 0, zoneid);
 		if (ire_need_rele)
 			ire_refrele(ire);
 		goto done;
@@ -25155,6 +25471,15 @@
 			goto drop_pkt;
 		}
 
+		DTRACE_PROBE4(ip4__physical__out__start, ill_t *, NULL,
+		    ill_t *, ire->ire_ipif->ipif_ill, ipha_t *, ipha,
+		    mblk_t *, mp);
+		FW_HOOKS(ip4_physical_out_event, ipv4firewall_physical_out,
+		    MSG_FWCOOKED_OUT, NULL, out_ill, ipha, mp, mp);
+		DTRACE_PROBE1(ip4__physical__out__end, mblk_t *, mp);
+		if (mp == NULL)
+			goto drop_pkt;
+
 		ip1dbg(("ip_wput_ipsec_out: calling ip_xmit_v4\n"));
 		pktxmit_state = ip_xmit_v4(mp, ire,
 		    (io->ipsec_out_accelerated ? io : NULL), B_FALSE);
@@ -25947,6 +26272,7 @@
     ipif_t *ipif, ipsq_t *ipsq)
 {
 	conn_t	*connp = NULL;
+	hook_nic_event_t *info;
 
 	if (err == EINPROGRESS)
 		return;
@@ -25986,6 +26312,26 @@
 	if (ipif != NULL) {
 		mutex_enter(&(ipif)->ipif_ill->ill_lock);
 		ipif->ipif_state_flags &= ~IPIF_CHANGING;
+
+		/*
+		 * Unhook the nic event message from the ill and enqueue it into
+		 * the nic event taskq.
+		 */
+		if ((info = ipif->ipif_ill->ill_nic_event_info) != NULL) {
+			if (ddi_taskq_dispatch(eventq_queue_nic,
+			    ip_ne_queue_func, (void *)info, DDI_SLEEP)
+			    == DDI_FAILURE) {
+				ip2dbg(("ip_ioctl_finish: ddi_taskq_dispatch"
+				    "failed\n"));
+				if (info->hne_data != NULL)
+					kmem_free(info->hne_data,
+					    info->hne_datalen);
+				kmem_free(info, sizeof (hook_nic_event_t));
+			}
+
+			ipif->ipif_ill->ill_nic_event_info = NULL;
+		}
+
 		mutex_exit(&(ipif)->ipif_ill->ill_lock);
 	}
 
@@ -28305,9 +28651,10 @@
 	nce_t		*arpce;
 	queue_t		*q;
 	int		ill_index;
-	mblk_t		*nxt_mp;
+	mblk_t		*nxt_mp, *first_mp;
 	boolean_t	xmit_drop = B_FALSE;
 	ip_proc_t	proc;
+	ill_t		*out_ill;
 
 	arpce = ire->ire_nce;
 	ASSERT(arpce != NULL);
@@ -28343,10 +28690,11 @@
 			mp->b_prev = NULL;
 
 			/* set up ill index for outbound qos processing */
-			ill_index =
-			    ire->ire_ipif->ipif_ill->ill_phyint->phyint_ifindex;
-			mp = ip_wput_attach_llhdr(mp, ire, proc, ill_index);
-			if (mp == NULL) {
+			out_ill = ire->ire_ipif->ipif_ill;
+			ill_index = out_ill->ill_phyint->phyint_ifindex;
+			first_mp = ip_wput_attach_llhdr(mp, ire, proc,
+			    ill_index);
+			if (first_mp == NULL) {
 				xmit_drop = B_TRUE;
 				if (proc == IPP_FWD_OUT) {
 					BUMP_MIB(&ip_mib, ipInDiscards);
@@ -28366,28 +28714,20 @@
 				}
 				ire->ire_last_used_time = lbolt;
 
-				if (flow_ctl_enabled) {
-					/*
-					 * We are here from ip_wout_ire
-					 * which has already done canput
-					 * check and has enabled flow
-					 * control, so skip the canputnext
-					 * check.
-					 */
-					putnext(q, mp);
-					goto next_mp;
-				}
-				if (canputnext(q))  {
+				if (flow_ctl_enabled || canputnext(q))  {
 					if (proc == IPP_FWD_OUT) {
 						BUMP_MIB(&ip_mib,
 						    ipForwDatagrams);
 					}
-					putnext(q, mp);
+
+					if (mp == NULL)
+						goto next_mp;
+					putnext(q, first_mp);
 				} else {
 					BUMP_MIB(&ip_mib,
 					    ipOutDiscards);
 					xmit_drop = B_TRUE;
-					freemsg(mp);
+					freemsg(first_mp);
 				}
 			} else {
 				/*
--- a/usr/src/uts/common/inet/ip/ip6.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ip/ip6.c	Fri Oct 20 16:37:58 2006 -0700
@@ -42,8 +42,11 @@
 #include <sys/sunddi.h>
 #include <sys/cmn_err.h>
 #include <sys/debug.h>
+#include <sys/sdt.h>
 #include <sys/kobj.h>
 #include <sys/zone.h>
+#include <sys/neti.h>
+#include <sys/hook.h>
 
 #include <sys/kmem.h>
 #include <sys/systm.h>
@@ -273,7 +276,7 @@
     conn_t *, int, int, int, zoneid_t);
 static boolean_t ip_ulp_cando_pkt2big(int);
 
-static void ip_rput_v6(queue_t *, mblk_t *);
+void ip_rput_v6(queue_t *, mblk_t *);
 static void ip_wput_v6(queue_t *, mblk_t *);
 
 /*
@@ -6692,7 +6695,10 @@
 		    B_FALSE, B_FALSE, GLOBAL_ZONEID);
 		return;
 	}
-	ip_rput_data_v6(q, ill, mp, ip6h, flags, hada_mp, dl_mp);
+	if (ip_check_v6_mblk(mp, ill) == 0) {
+		ip6h = (ip6_t *)mp->b_rptr;
+		ip_rput_data_v6(q, ill, mp, ip6h, flags, hada_mp, dl_mp);
+	}
 	return;
 hada_drop:
 	/* IPsec kstats: bean counter? */
@@ -6703,7 +6709,7 @@
 /*
  * Read side put procedure for IPv6 module.
  */
-static void
+void
 ip_rput_v6(queue_t *q, mblk_t *mp)
 {
 	mblk_t		*first_mp;
@@ -6901,17 +6907,23 @@
 		mp = first_mp->b_cont;
 	}
 
+	if (ip_check_v6_mblk(mp, ill) == -1)
+		return;
+
 	ip6h = (ip6_t *)mp->b_rptr;
 
-	/* check for alignment and full IPv6 header */
-	if (!OK_32PTR((uchar_t *)ip6h) ||
-	    (mp->b_wptr - (uchar_t *)ip6h) < IPV6_HDR_LEN) {
-		if (!pullupmsg(mp, IPV6_HDR_LEN)) {
-			ip1dbg(("ip_rput_v6: pullupmsg failed\n"));
-			goto discard;
-		}
-		ip6h = (ip6_t *)mp->b_rptr;
-	}
+	DTRACE_PROBE4(ip6__physical__in__start,
+	    ill_t *, ill, ill_t *, NULL,
+	    ip6_t *, ip6h, mblk_t *, first_mp);
+
+	FW_HOOKS6(ip6_physical_in_event, ipv6firewall_physical_in,
+	    MSG_FWCOOKED_IN, ill, NULL, ip6h, first_mp, mp);
+
+	DTRACE_PROBE1(ip6__physical__in__end, mblk_t *, first_mp);
+
+	if (first_mp == NULL) 
+		return;
+
 	if ((ip6h->ip6_vcf & IPV6_VERS_AND_FLOW_MASK) ==
 	    IPV6_DEFAULT_VERS_AND_FLOW) {
 		/*
@@ -7137,6 +7149,62 @@
 }
 
 /*
+ * Validate the IPv6 mblk for alignment.
+ */
+int
+ip_check_v6_mblk(mblk_t *mp, ill_t *ill)
+{
+	int pkt_len, ip6_len;
+	ip6_t *ip6h = (ip6_t *)mp->b_rptr;
+
+	/* check for alignment and full IPv6 header */
+	if (!OK_32PTR((uchar_t *)ip6h) ||
+	    (mp->b_wptr - (uchar_t *)ip6h) < IPV6_HDR_LEN) {
+		if (!pullupmsg(mp, IPV6_HDR_LEN)) {
+			BUMP_MIB(ill->ill_ip6_mib, ipv6InDiscards);
+			ip1dbg(("ip_rput_v6: pullupmsg failed\n"));
+			freemsg(mp);
+			return (-1);
+		}
+		ip6h = (ip6_t *)mp->b_rptr;
+	}
+
+	ASSERT(OK_32PTR((uchar_t *)ip6h) &&
+	    (mp->b_wptr - (uchar_t *)ip6h) >= IPV6_HDR_LEN);
+
+	if (mp->b_cont == NULL)
+		pkt_len = mp->b_wptr - mp->b_rptr;
+	else
+		pkt_len = msgdsize(mp);
+	ip6_len = ntohs(ip6h->ip6_plen) + IPV6_HDR_LEN;
+
+	/*
+	 * Check for bogus (too short packet) and packet which
+	 * was padded by the link layer.
+	 */
+	if (ip6_len != pkt_len) {
+		ssize_t diff;
+
+		if (ip6_len > pkt_len) {
+			ip1dbg(("ip_rput_data_v6: packet too short %d %d\n",
+			    ip6_len, pkt_len));
+			BUMP_MIB(ill->ill_ip6_mib, ipv6InTruncatedPkts);
+			freemsg(mp);
+			return (-1);
+		}
+		diff = (ssize_t)(pkt_len - ip6_len);
+
+		if (!adjmsg(mp, -diff)) {
+			ip1dbg(("ip_rput_data_v6: adjmsg failed\n"));
+			BUMP_MIB(ill->ill_ip6_mib, ipv6InDiscards);
+			freemsg(mp);
+			return (-1);
+		}
+	}
+	return (0);
+}
+
+/*
  * ip_rput_data_v6 -- received IPv6 packets in M_DATA messages show up here.
  * ip_rput_v6 has already verified alignment, the min length, the version,
  * and db_ref = 1.
@@ -7157,6 +7225,7 @@
 	ire_t		*ire = NULL;
 	queue_t		*rq;
 	ill_t		*ill = inill;
+	ill_t		*outill;
 	ipif_t		*ipif;
 	uint8_t		*whereptr;
 	uint8_t		nexthdr;
@@ -7201,41 +7270,9 @@
 		ASSERT(mp->b_datap->db_type != M_CTL);
 	}
 
-	ASSERT(OK_32PTR((uchar_t *)ip6h) &&
-	    (mp->b_wptr - (uchar_t *)ip6h) >= IPV6_HDR_LEN);
-
-	if (mp->b_cont == NULL)
-		pkt_len = mp->b_wptr - mp->b_rptr;
-	else
-		pkt_len = msgdsize(mp);
+	ip6h = (ip6_t *)mp->b_rptr;
 	ip6_len = ntohs(ip6h->ip6_plen) + IPV6_HDR_LEN;
-
-	/*
-	 * Check for bogus (too short packet) and packet which
-	 * was padded by the link layer.
-	 */
-	if (ip6_len != pkt_len) {
-		ssize_t diff;
-
-		if (ip6_len > pkt_len) {
-			ip1dbg(("ip_rput_data_v6: packet too short %d %lu\n",
-			    ip6_len, pkt_len));
-			BUMP_MIB(ill->ill_ip6_mib, ipv6InTruncatedPkts);
-			freemsg(hada_mp);
-			freemsg(first_mp);
-			return;
-		}
-		diff = (ssize_t)(pkt_len - ip6_len);
-
-		if (!adjmsg(mp, -diff)) {
-			ip1dbg(("ip_rput_data_v6: adjmsg failed\n"));
-			BUMP_MIB(ill->ill_ip6_mib, ipv6InDiscards);
-			freemsg(hada_mp);
-			freemsg(first_mp);
-			return;
-		}
-		pkt_len -= diff;
-	}
+	pkt_len = ip6_len;
 
 	if (ILL_HCKSUM_CAPABLE(ill) && !mctl_present && dohwcksum)
 		hck_flags = DB_CKSUMFLAGS(mp);
@@ -7593,10 +7630,24 @@
 forward:
 		/* Hoplimit verified above */
 		ip6h->ip6_hops--;
-		UPDATE_IB_PKT_COUNT(ire);
-		ire->ire_last_used_time = lbolt;
-		BUMP_MIB(ill->ill_ip6_mib, ipv6OutForwDatagrams);
-		ip_xmit_v6(mp, ire, 0, NULL, B_FALSE, NULL);
+
+		outill = ire->ire_ipif->ipif_ill;
+
+		DTRACE_PROBE4(ip6__forwarding__start,
+		    ill_t *, inill, ill_t *, outill,
+		    ip6_t *, ip6h, mblk_t *, mp);
+
+		FW_HOOKS6(ip6_forwarding_event, ipv6firewall_forwarding,
+		    MSG_FWCOOKED_FORWARD, inill, outill, ip6h, mp, mp);
+
+		DTRACE_PROBE1(ip6__forwarding__end, mblk_t *, mp);
+
+		if (mp != NULL) {
+			UPDATE_IB_PKT_COUNT(ire);
+			ire->ire_last_used_time = lbolt;
+			BUMP_MIB(ill->ill_ip6_mib, ipv6OutForwDatagrams);
+			ip_xmit_v6(mp, ire, 0, NULL, B_FALSE, NULL);
+		}
 		IRE_REFRELE(ire);
 		return;
 	}
@@ -10544,6 +10595,20 @@
 	}
 
 
+	DTRACE_PROBE4(ip6__loopback__in__start,
+	    ill_t *, ill, ill_t *, NULL,
+	    ip6_t *, ip6h, mblk_t *, first_mp);
+
+	FW_HOOKS6(ip6_loopback_in_event, ipv6firewall_loopback_in,
+	    MSG_FWCOOKED_IN, ill, NULL, ip6h, first_mp, mp);
+
+	DTRACE_PROBE1(ip6__loopback__in__end, mblk_t *, first_mp);
+
+	if (first_mp == NULL)
+		return;
+
+	nexthdr = ip6h->ip6_nxt;
+
 	UPDATE_OB_PKT_COUNT(ire);
 	ire->ire_last_used_time = lbolt;
 
@@ -10909,20 +10974,45 @@
 				nmp = ip_copymsg(first_mp);
 				if (nmp != NULL) {
 					ip6_t	*nip6h;
+					mblk_t	*mp_ip6h;
 
 					if (mctl_present) {
 						nip6h = (ip6_t *)
 						    nmp->b_cont->b_rptr;
+						mp_ip6h = nmp->b_cont;
 					} else {
 						nip6h = (ip6_t *)nmp->b_rptr;
+						mp_ip6h = nmp;
 					}
-					/*
-					 * Deliver locally and to every local
-					 * zone, except the sending zone when
-					 * IPV6_MULTICAST_LOOP is disabled.
-					 */
-					ip_wput_local_v6(RD(q), ill, nip6h, nmp,
-					    ire, fanout_flags);
+
+					DTRACE_PROBE4(
+					    ip6__loopback__out__start,
+					    ill_t *, NULL,
+					    ill_t *, ill,
+					    ip6_t *, nip6h,
+					    mblk_t *, nmp);
+
+					FW_HOOKS6(ip6_loopback_out_event,
+					    ipv6firewall_loopback_out,
+					    MSG_FWCOOKED_OUT, NULL, ill,
+					    nip6h, nmp, mp_ip6h);
+
+					DTRACE_PROBE1(
+					    ip6__loopback__out__end,
+					    mblk_t *, nmp);
+
+					if (nmp != NULL) {
+						/*
+						 * Deliver locally and to
+						 * every local zone, except
+						 * the sending zone when
+						 * IPV6_MULTICAST_LOOP is
+						 * disabled.
+						 */
+						ip_wput_local_v6(RD(q), ill,
+						    nip6h, nmp,
+						    ire, fanout_flags);
+					}
 				} else {
 					BUMP_MIB(mibptr, ipv6OutDiscards);
 					ip1dbg(("ip_wput_ire_v6: "
@@ -11336,7 +11426,14 @@
 		ASSERT(mp == first_mp);
 		ip_xmit_v6(mp, ire, reachable, connp, caller, NULL);
 	} else {
-		ip_wput_local_v6(RD(q), ill, ip6h, first_mp, ire, 0);
+		DTRACE_PROBE4(ip6__loopback__out__start,
+		    ill_t *, NULL, ill_t *, ill,
+		    ip6_t *, ip6h, mblk_t *, first_mp);
+		FW_HOOKS6(ip6_loopback_out_event, ipv6firewall_loopback_out,
+		    MSG_FWCOOKED_OUT, NULL, ill, ip6h, first_mp, mp);
+		DTRACE_PROBE1(ip6__loopback__out__end, mblk_t *, first_mp);
+		if (first_mp != NULL)
+			ip_wput_local_v6(RD(q), ill, ip6h, first_mp, ire, 0);
 	}
 }
 
@@ -11871,6 +11968,7 @@
 	mblk_t		*mp1;
 	nce_t		*nce = ire->ire_nce;
 	ill_t		*ill;
+	ill_t		*out_ill;
 	uint64_t	delta;
 	ip6_t		*ip6h;
 	queue_t		*stq = ire->ire_stq;
@@ -11994,7 +12092,7 @@
 		}
 
 		do {
-			boolean_t	qos_done = B_FALSE;
+			mblk_t *mp_ip6h;
 
 			if (multirt_send) {
 				irb_t *irb;
@@ -12055,6 +12153,23 @@
 			ill_index =
 			    ((ill_t *)stq->q_ptr)->ill_phyint->phyint_ifindex;
 
+			/* Initiate IPPF processing */
+			if (IP6_OUT_IPP(flags)) {
+				ip_process(IPP_LOCAL_OUT, &mp, ill_index);
+				if (mp == NULL) {
+					BUMP_MIB(ill->ill_ip6_mib,
+					    ipv6OutDiscards);
+					if (next_mp != NULL)
+						freemsg(next_mp);
+					if (ire != save_ire) {
+						ire_refrele(ire);
+					}
+					return;
+				}
+				ip6h = (ip6_t *)mp->b_rptr;
+			}
+			mp_ip6h = mp;
+
 			/*
 			 * Check for fastpath, we need to hold nce_lock to
 			 * prevent fastpath update from chaining nce_fp_mp.
@@ -12066,39 +12181,6 @@
 				uint32_t hlen;
 				uchar_t	*rptr;
 
-				/* Initiate IPPF processing */
-				if (IP6_OUT_IPP(flags)) {
-					/*
-					 * We have to release the nce lock since
-					 * IPPF components use
-					 * ill_lookup_on_ifindex(),
-					 * which takes the ill_g_lock and the
-					 * ill_lock locks.
-					 */
-					mutex_exit(&nce->nce_lock);
-					ip_process(IPP_LOCAL_OUT, &mp,
-					    ill_index);
-					if (mp == NULL) {
-						BUMP_MIB(
-						    ill->ill_ip6_mib,
-						    ipv6OutDiscards);
-						if (next_mp != NULL)
-							freemsg(next_mp);
-						if (ire != save_ire) {
-							ire_refrele(ire);
-						}
-						return;
-					}
-					mutex_enter(&nce->nce_lock);
-					if ((mp1 = nce->nce_fp_mp) == NULL) {
-						/*
-						 * Probably disappeared during
-						 * IPQoS processing.
-						 */
-						qos_done = B_TRUE;
-						goto prepend_unitdata;
-					}
-				}
 				hlen = MBLKL(mp1);
 				rptr = mp->b_rptr - hlen;
 				/*
@@ -12107,8 +12189,8 @@
 				 */
 				if (rptr < mp->b_datap->db_base) {
 					mp1 = copyb(mp1);
+					mutex_exit(&nce->nce_lock);
 					if (mp1 == NULL) {
-						mutex_exit(&nce->nce_lock);
 						BUMP_MIB(ill->ill_ip6_mib,
 						    ipv6OutDiscards);
 						freemsg(mp);
@@ -12131,15 +12213,15 @@
 					 * header
 					 */
 					bcopy(mp1->b_rptr, rptr, hlen);
-				}
-
-				mutex_exit(&nce->nce_lock);
-
+					mutex_exit(&nce->nce_lock);
+				}
 			} else {
-		prepend_unitdata:
-				mutex_exit(&nce->nce_lock);
+				/*
+				 * Get the DL_UNITDATA_REQ.
+				 */
 				mp1 = nce->nce_res_mp;
 				if (mp1 == NULL) {
+					mutex_exit(&nce->nce_lock);
 					ip1dbg(("ip_xmit_v6: No resolution "
 					    "block ire = %p\n", (void *)ire));
 					freemsg(mp);
@@ -12154,6 +12236,7 @@
 				 * Prepend the DL_UNITDATA_REQ.
 				 */
 				mp1 = copyb(mp1);
+				mutex_exit(&nce->nce_lock);
 				if (mp1 == NULL) {
 					BUMP_MIB(ill->ill_ip6_mib,
 					    ipv6OutDiscards);
@@ -12166,24 +12249,47 @@
 					return;
 				}
 				mp1->b_cont = mp;
+
+				/* Get the priority marking, if any */
+				mp1->b_band = mp->b_band;
 				mp = mp1;
-				/*
-				 * Initiate IPPF processing, if it is
-				 * already done, bypass.
-				 */
-				if (!qos_done && IP6_OUT_IPP(flags)) {
-					ip_process(IPP_LOCAL_OUT, &mp,
-					    ill_index);
-					if (mp == NULL) {
-						BUMP_MIB(ill->ill_ip6_mib,
-						    ipv6OutDiscards);
-						if (next_mp != NULL)
-							freemsg(next_mp);
-						if (ire != save_ire) {
-							ire_refrele(ire);
-						}
-						return;
+			}
+
+			out_ill = (ill_t *)stq->q_ptr;
+
+			DTRACE_PROBE4(ip6__physical__out__start,
+			    ill_t *, NULL, ill_t *, out_ill,
+			    ip6_t *, ip6h, mblk_t *, mp);
+
+			FW_HOOKS6(ip6_physical_out_event,
+			    ipv6firewall_physical_out, MSG_FWCOOKED_OUT,
+			    NULL, out_ill, ip6h, mp, mp_ip6h);
+
+			DTRACE_PROBE1(ip6__physical__out__end, mblk_t *, mp);
+
+			if (mp == NULL) {
+				if (multirt_send) {
+					ASSERT(ire1 != NULL);
+					if (ire != save_ire) {
+						ire_refrele(ire);
 					}
+					/*
+					 * Proceed with the next RTF_MULTIRT
+					 * ire, also set up the send-to queue
+					 * accordingly.
+					 */
+					ire = ire1;
+					ire1 = NULL;
+					stq = ire->ire_stq;
+					nce = ire->ire_nce;
+					ill = ire_to_ill(ire);
+					mp = next_mp;
+					next_mp = NULL;
+					continue;
+				} else {
+					ASSERT(next_mp == NULL);
+					ASSERT(ire1 == NULL);
+					break;
 				}
 			}
 
--- a/usr/src/uts/common/inet/ip/ip_ftable.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ip/ip_ftable.c	Fri Oct 20 16:37:58 2006 -0700
@@ -1293,6 +1293,7 @@
 
 		ire = ire_route_lookup(dst, 0, 0, 0, supplied_ipif,
 		    &sire, zoneid, MBLK_GETLABEL(mp), match_flags);
+		ipif_refrele(supplied_ipif);
 		ill_refrele(ill);
 	}
 
@@ -1325,7 +1326,7 @@
 		goto discard;
 	}
 
-	ASSERT(ire->ire_nce != NULL);
+	ASSERT(ire->ire_type != IRE_CACHE || ire->ire_nce != NULL);
 	/*
 	 * If needed, we will create the ire cache entry for the
 	 * nexthop, resolve its link-layer address and then send
--- a/usr/src/uts/common/inet/ip/ip_if.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ip/ip_if.c	Fri Oct 20 16:37:58 2006 -0700
@@ -81,6 +81,7 @@
 #include <inet/ip_impl.h>
 #include <inet/tun.h>
 #include <inet/sctp_ip.h>
+#include <inet/ip_netinfo.h>
 
 #include <net/pfkeyv2.h>
 #include <inet/ipsec_info.h>
@@ -4207,16 +4208,35 @@
 	mi_free(interface);
 }
 
+/* Defined in ip_netinfo.c */
+extern ddi_taskq_t	*eventq_queue_nic;
+
 /*
  * remove ill from the global list.
  */
 static void
 ill_glist_delete(ill_t *ill)
 {
+	char *nicname;
+	size_t nicnamelen;
+	hook_nic_event_t *info;
+
 	if (ill == NULL)
 		return;
 
 	rw_enter(&ill_g_lock, RW_WRITER);
+
+	if (ill->ill_name != NULL) {
+		nicname = kmem_alloc(ill->ill_name_length, KM_NOSLEEP);
+		if (nicname != NULL) {
+			bcopy(ill->ill_name, nicname, ill->ill_name_length);
+			nicnamelen = ill->ill_name_length;
+		}
+	} else {
+		nicname = NULL;
+		nicnamelen = 0;
+	}
+
 	/*
 	 * If the ill was never inserted into the AVL tree
 	 * we skip the if branch.
@@ -4243,7 +4263,56 @@
 		ill->ill_name[0] = '\0';
 		ill->ill_ppa = UINT_MAX;
 	}
+
+	/*
+	 * Run the unplumb hook after the NIC has disappeared from being
+	 * visible so that attempts to revalidate its existance will fail.
+	 *
+	 * This needs to be run inside the ill_g_lock perimeter to ensure
+	 * that the ordering of delivered events to listeners matches the
+	 * order of them in the kernel.
+	 */
+	if ((info = ill->ill_nic_event_info) != NULL) {
+		if (info->hne_event != NE_DOWN) {
+			ip2dbg(("ill_glist_delete: unexpected nic event %d "
+			    "attached for %s\n", info->hne_event,
+			    ill->ill_name));
+			if (info->hne_data != NULL)
+				kmem_free(info->hne_data, info->hne_datalen);
+			kmem_free(info, sizeof (hook_nic_event_t));
+		} else {
+			if (ddi_taskq_dispatch(eventq_queue_nic,
+			    ip_ne_queue_func, (void *)info, DDI_SLEEP)
+			    == DDI_FAILURE) {
+				ip2dbg(("ill_glist_delete: ddi_taskq_dispatch "
+				    "failed\n"));
+				if (info->hne_data != NULL)
+					kmem_free(info->hne_data,
+					    info->hne_datalen);
+				kmem_free(info, sizeof (hook_nic_event_t));
+			}
+		}
+	}
+
+	info = kmem_alloc(sizeof (hook_nic_event_t), KM_NOSLEEP);
+	if (info != NULL) {
+		info->hne_nic = ill->ill_phyint->phyint_ifindex;
+		info->hne_lif = 0;
+		info->hne_event = NE_UNPLUMB;
+		info->hne_data = nicname;
+		info->hne_datalen = nicnamelen;
+		info->hne_family = ill->ill_isv6 ? ipv6 : ipv4;
+	} else {
+		ip2dbg(("ill_glist_delete: could not attach UNPLUMB nic event "
+		    "information for %s (ENOMEM)\n", ill->ill_name));
+		if (nicname != NULL)
+			kmem_free(nicname, nicnamelen);
+	}
+
+	ill->ill_nic_event_info = info;
+
 	ill_phyint_free(ill);
+
 	rw_exit(&ill_g_lock);
 }
 
@@ -4996,6 +5065,88 @@
 }
 
 /*
+ * Return the ifindex next in sequence after the passed in ifindex.
+ * If there is no next ifindex for the given protocol, return 0.
+ */
+uint_t
+ill_get_next_ifindex(uint_t index, boolean_t isv6)
+{
+	phyint_t *phyi;
+	phyint_t *phyi_initial;
+	uint_t   ifindex;
+
+	rw_enter(&ill_g_lock, RW_READER);
+
+	if (index == 0) {
+		phyi = avl_first(&phyint_g_list.phyint_list_avl_by_index);
+	} else {
+		phyi = phyi_initial = avl_find(
+		    &phyint_g_list.phyint_list_avl_by_index,
+		    (void *) &index, NULL);
+	}
+
+	for (; phyi != NULL;
+	    phyi = avl_walk(&phyint_g_list.phyint_list_avl_by_index,
+	    phyi, AVL_AFTER)) {
+		/*
+		 * If we're not returning the first interface in the tree
+		 * and we still haven't moved past the phyint_t that
+		 * corresponds to index, avl_walk needs to be called again
+		 */
+		if (!((index != 0) && (phyi == phyi_initial))) {
+			if (isv6) {
+				if ((phyi->phyint_illv6) &&
+				    ILL_CAN_LOOKUP(phyi->phyint_illv6) &&
+				    (phyi->phyint_illv6->ill_isv6 == 1))
+					break;
+			} else {
+				if ((phyi->phyint_illv4) &&
+				    ILL_CAN_LOOKUP(phyi->phyint_illv4) &&
+				    (phyi->phyint_illv4->ill_isv6 == 0))
+					break;
+			}
+		}
+	}
+
+	rw_exit(&ill_g_lock);
+
+	if (phyi != NULL)
+		ifindex = phyi->phyint_ifindex;
+	else
+		ifindex = 0;
+
+	return (ifindex);
+}
+
+
+/*
+ * Return the ifindex for the named interface.
+ * If there is no next ifindex for the interface, return 0.
+ */
+uint_t
+ill_get_ifindex_by_name(char *name)
+{
+	phyint_t	*phyi;
+	avl_index_t	where = 0;
+	uint_t		ifindex;
+
+	rw_enter(&ill_g_lock, RW_READER);
+
+	if ((phyi = avl_find(&phyint_g_list.phyint_list_avl_by_name,
+	    name, &where)) == NULL) {
+		rw_exit(&ill_g_lock);
+		return (0);
+	}
+
+	ifindex = phyi->phyint_ifindex;
+
+	rw_exit(&ill_g_lock);
+
+	return (ifindex);
+}
+
+
+/*
  * Obtain a reference to the ill. The ill_refcnt is a dynamic refcnt
  * that gives a running thread a reference to the ill. This reference must be
  * released by the thread when it is done accessing the ill and related
@@ -10821,10 +10972,12 @@
 	in6_addr_t v6addr;
 	ipaddr_t addr;
 	sin6_t	*sin6;
+	int	sinlen;
 	int	err = 0;
 	ill_t	*ill = ipif->ipif_ill;
 	boolean_t need_dl_down;
 	boolean_t need_arp_down;
+	struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
 
 	ip1dbg(("ip_sioctl_addr_tail(%s:%u %p)\n",
 	    ill->ill_name, ipif->ipif_id, (void *)ipif));
@@ -10838,9 +10991,11 @@
 	if (ipif->ipif_isv6) {
 		sin6 = (sin6_t *)sin;
 		v6addr = sin6->sin6_addr;
+		sinlen = sizeof (struct sockaddr_in6);
 	} else {
 		addr = sin->sin_addr.s_addr;
 		IN6_IPADDR_TO_V4MAPPED(addr, &v6addr);
+		sinlen = sizeof (struct sockaddr_in);
 	}
 	mutex_enter(&ill->ill_lock);
 	ipif->ipif_v6lcl_addr = v6addr;
@@ -10897,7 +11052,53 @@
 	}
 
 	ipif_set_default(ipif);
-	mutex_exit(&ill->ill_lock);
+
+	/*
+	 * When publishing an interface address change event, we only notify
+	 * the event listeners of the new address.  It is assumed that if they
+	 * actively care about the addresses assigned that they will have
+	 * already discovered the previous address assigned (if there was one.)
+	 *
+	 * Don't attach nic event message for SIOCLIFADDIF ioctl.
+	 */
+	if (iocp->ioc_cmd != SIOCLIFADDIF) {
+		hook_nic_event_t *info;
+		if ((info = ipif->ipif_ill->ill_nic_event_info) != NULL) {
+			ip2dbg(("ip_sioctl_addr_tail: unexpected nic event %d "
+			    "attached for %s\n", info->hne_event,
+			    ill->ill_name));
+			if (info->hne_data != NULL)
+				kmem_free(info->hne_data, info->hne_datalen);
+			kmem_free(info, sizeof (hook_nic_event_t));
+		}
+
+		info = kmem_alloc(sizeof (hook_nic_event_t), KM_NOSLEEP);
+		if (info != NULL) {
+			info->hne_nic =
+			    ipif->ipif_ill->ill_phyint->phyint_ifindex;
+			info->hne_lif = MAP_IPIF_ID(ipif->ipif_id);
+			info->hne_event = NE_ADDRESS_CHANGE;
+			info->hne_family = ipif->ipif_isv6 ? ipv6 : ipv4;
+			info->hne_data = kmem_alloc(sinlen, KM_NOSLEEP);
+			if (info->hne_data != NULL) {
+				info->hne_datalen = sinlen;
+				bcopy(sin, info->hne_data, sinlen);
+			} else {
+				ip2dbg(("ip_sioctl_addr_tail: could not attach "
+				    "address information for ADDRESS_CHANGE nic"
+				    " event of %s (ENOMEM)\n",
+				    ipif->ipif_ill->ill_name));
+				kmem_free(info, sizeof (hook_nic_event_t));
+			}
+		} else
+			ip2dbg(("ip_sioctl_addr_tail: could not attach "
+			    "ADDRESS_CHANGE nic event information for %s "
+			    "(ENOMEM)\n", ipif->ipif_ill->ill_name));
+
+		ipif->ipif_ill->ill_nic_event_info = info;
+	}
+
+	mutex_exit(&ipif->ipif_ill->ill_lock);
 
 	if (need_up) {
 		/*
@@ -17669,6 +17870,7 @@
 	 * is brought up.
 	 */
 	mblk_t	*mp = ill->ill_unbind_mp;
+	hook_nic_event_t *info;
 
 	ip1dbg(("ill_dl_down(%s)\n", ill->ill_name));
 
@@ -17695,7 +17897,31 @@
 	ill_leave_multicast(ill);
 
 	mutex_enter(&ill->ill_lock);
+
 	ill->ill_dl_up = 0;
+
+	if ((info = ill->ill_nic_event_info) != NULL) {
+		ip2dbg(("ill_dl_down:unexpected nic event %d attached for %s\n",
+		    info->hne_event, ill->ill_name));
+		if (info->hne_data != NULL)
+			kmem_free(info->hne_data, info->hne_datalen);
+		kmem_free(info, sizeof (hook_nic_event_t));
+	}
+
+	info = kmem_alloc(sizeof (hook_nic_event_t), KM_NOSLEEP);
+	if (info != NULL) {
+		info->hne_nic = ill->ill_phyint->phyint_ifindex;
+		info->hne_lif = 0;
+		info->hne_event = NE_DOWN;
+		info->hne_data = NULL;
+		info->hne_datalen = 0;
+		info->hne_family = ill->ill_isv6 ? ipv6 : ipv4;
+	} else
+		ip2dbg(("ill_dl_down: could not attach DOWN nic event "
+		    "information for %s (ENOMEM)\n", ill->ill_name));
+
+	ill->ill_nic_event_info = info;
+
 	mutex_exit(&ill->ill_lock);
 }
 
@@ -19746,8 +19972,8 @@
 	rw_enter(&ill_g_lock, RW_READER);
 	mutex_enter(&ip_addr_avail_lock);
 	/* Mark it up, and increment counters. */
+	ipif->ipif_flags |= IPIF_UP;
 	ill->ill_ipif_up_count++;
-	ipif->ipif_flags |= IPIF_UP;
 	err = ip_addr_availability_check(ipif);
 	mutex_exit(&ip_addr_avail_lock);
 	rw_exit(&ill_g_lock);
@@ -22110,6 +22336,57 @@
 		    ill->ill_phyint->phyint_ifindex;
 	}
 
+	/*
+	 * Generate an event within the hooks framework to indicate that
+	 * a new interface has just been added to IP.  For this event to
+	 * be generated, the network interface must, at least, have an
+	 * ifindex assigned to it.
+	 *
+	 * This needs to be run inside the ill_g_lock perimeter to ensure
+	 * that the ordering of delivered events to listeners matches the
+	 * order of them in the kernel.
+	 *
+	 * This function could be called from ill_lookup_on_name. In that case
+	 * the interface is loopback "lo", which will not generate a NIC event.
+	 */
+	if (ill->ill_name_length <= 2 ||
+	    ill->ill_name[0] != 'l' || ill->ill_name[1] != 'o') {
+		hook_nic_event_t *info;
+		if ((info = ill->ill_nic_event_info) != NULL) {
+			ip2dbg(("ill_phyint_reinit: unexpected nic event %d "
+			    "attached for %s\n", info->hne_event,
+			    ill->ill_name));
+			if (info->hne_data != NULL)
+				kmem_free(info->hne_data, info->hne_datalen);
+			kmem_free(info, sizeof (hook_nic_event_t));
+		}
+
+		info = kmem_alloc(sizeof (hook_nic_event_t), KM_NOSLEEP);
+		if (info != NULL) {
+			info->hne_nic = ill->ill_phyint->phyint_ifindex;
+			info->hne_lif = 0;
+			info->hne_event = NE_PLUMB;
+			info->hne_family = ill->ill_isv6 ? ipv6 : ipv4;
+			info->hne_data = kmem_alloc(ill->ill_name_length,
+			    KM_NOSLEEP);
+			if (info->hne_data != NULL) {
+				info->hne_datalen = ill->ill_name_length;
+				bcopy(ill->ill_name, info->hne_data,
+				    info->hne_datalen);
+			} else {
+				ip2dbg(("ill_phyint_reinit: could not attach "
+				    "ill_name information for PLUMB nic event "
+				    "of %s (ENOMEM)\n", ill->ill_name));
+				kmem_free(info, sizeof (hook_nic_event_t));
+			}
+		} else
+			ip2dbg(("ill_phyint_reinit: could not attach PLUMB nic "
+			    "event information for %s (ENOMEM)\n",
+			    ill->ill_name));
+
+		ill->ill_nic_event_info = info;
+	}
+
 	RELEASE_ILL_LOCKS(ill, ill_other);
 	mutex_exit(&phyi->phyint_lock);
 }
@@ -23599,3 +23876,40 @@
 
 	return (B_FALSE);
 }
+
+/*
+ * Return a pointer to an ipif_t given a combination of (ill_idx,ipif_id)
+ * If a pointer to an ipif_t is returned then the caller will need to do
+ * an ill_refrele().
+ */
+ipif_t *
+ipif_getby_indexes(uint_t ifindex, uint_t lifidx, boolean_t isv6)
+{
+	ipif_t *ipif;
+	ill_t *ill;
+
+	ill = ill_lookup_on_ifindex(ifindex, isv6, NULL, NULL, NULL, NULL);
+
+	if (ill == NULL)
+		return (NULL);
+
+	mutex_enter(&ill->ill_lock);
+	if (ill->ill_state_flags & ILL_CONDEMNED) {
+		mutex_exit(&ill->ill_lock);
+		ill_refrele(ill);
+		return (NULL);
+	}
+
+	for (ipif = ill->ill_ipif; ipif != NULL; ipif = ipif->ipif_next) {
+		if (!IPIF_CAN_LOOKUP(ipif))
+			continue;
+		if (lifidx == ipif->ipif_id) {
+			ipif_refhold_locked(ipif);
+			break;
+		}
+	}
+
+	mutex_exit(&ill->ill_lock);
+	ill_refrele(ill);
+	return (ipif);
+}
--- a/usr/src/uts/common/inet/ip/ip_multi.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ip/ip_multi.c	Fri Oct 20 16:37:58 2006 -0700
@@ -33,6 +33,7 @@
 #include <sys/strsun.h>
 #include <sys/ddi.h>
 #include <sys/cmn_err.h>
+#include <sys/sdt.h>
 #include <sys/zone.h>
 
 #include <sys/param.h>
@@ -1181,6 +1182,7 @@
 {
 	mblk_t	*mp;
 	mblk_t	*ipsec_mp;
+	ipha_t	*iph;
 
 	if (DB_TYPE(mp_orig) == M_DATA &&
 	    ((ipha_t *)mp_orig->b_rptr)->ipha_protocol == IPPROTO_UDP) {
@@ -1217,8 +1219,21 @@
 	} else {
 		ipsec_mp = mp;
 	}
-	ip_wput_local(q, ill, (ipha_t *)mp->b_rptr, ipsec_mp, NULL,
-	    fanout_flags, zoneid);
+
+	iph = (ipha_t *)mp->b_rptr;
+
+	DTRACE_PROBE4(ip4__loopback__out__start,
+	    ill_t *, NULL, ill_t *, ill,
+	    ipha_t *, iph, mblk_t *, ipsec_mp);
+
+	FW_HOOKS(ip4_loopback_out_event, ipv4firewall_loopback_out,
+	    MSG_FWCOOKED_OUT, NULL, ill, iph, ipsec_mp, mp);
+
+	DTRACE_PROBE1(ip4__loopback__out__end, mblk_t *, ipsec_mp);
+
+	if (ipsec_mp != NULL)
+		ip_wput_local(q, ill, iph, ipsec_mp, NULL,
+		    fanout_flags, zoneid);
 }
 
 static area_t	ip_aresq_template = {
--- a/usr/src/uts/common/inet/ip/ip_ndp.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ip/ip_ndp.c	Fri Oct 20 16:37:58 2006 -0700
@@ -526,9 +526,8 @@
 
 			mp = *mpp;
 			*mpp = mp->b_next;
-			mp->b_next = NULL;
-			mp->b_prev = NULL;
-			freemsg(mp);
+
+			inet_freemsg(mp);
 		}
 	} while (mpp++ != &nce->nce_last_mp_to_free);
 
@@ -551,7 +550,8 @@
 		mutex_exit(&ill->ill_lock);
 	}
 	mutex_destroy(&nce->nce_lock);
-	freeb(nce->nce_mp);
+	if (nce->nce_mp != NULL)
+		inet_freemsg(nce->nce_mp);
 }
 
 /*
@@ -836,26 +836,31 @@
 		nce->nce_qd_mp = NULL;
 		mutex_exit(&nce->nce_lock);
 		while (mp != NULL) {
-			mblk_t *nxt_mp;
+			mblk_t *nxt_mp, *data_mp;
 
 			nxt_mp = mp->b_next;
 			mp->b_next = NULL;
-			if (mp->b_prev != NULL) {
+
+			if (mp->b_datap->db_type == M_CTL)
+				data_mp = mp->b_cont;
+			else
+				data_mp = mp;
+			if (data_mp->b_prev != NULL) {
 				ill_t   *inbound_ill;
 				queue_t *fwdq = NULL;
 				uint_t ifindex;
 
-				ifindex = (uint_t)(uintptr_t)mp->b_prev;
+				ifindex = (uint_t)(uintptr_t)data_mp->b_prev;
 				inbound_ill = ill_lookup_on_ifindex(ifindex,
 				    B_TRUE, NULL, NULL, NULL, NULL);
 				if (inbound_ill == NULL) {
-					mp->b_prev = NULL;
+					data_mp->b_prev = NULL;
 					freemsg(mp);
 					return;
 				} else {
 					fwdq = inbound_ill->ill_rq;
 				}
-				mp->b_prev = NULL;
+				data_mp->b_prev = NULL;
 				/*
 				 * Send a forwarded packet back into ip_rput_v6
 				 * just as in ire_send_v6().
@@ -867,7 +872,9 @@
 					 * Forwarded packets hop count will
 					 * get decremented in ip_rput_data_v6
 					 */
-					put(fwdq, mp);
+					if (data_mp != mp)
+						freeb(mp);
+					put(fwdq, data_mp);
 				} else {
 					/*
 					 * Send locally originated packets back
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/inet/ip/ip_netinfo.c	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,1321 @@
+/*
+ * 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 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/stream.h>
+#include <sys/strsubr.h>
+#include <sys/pattr.h>
+#include <sys/dlpi.h>
+#include <sys/atomic.h>
+#include <sys/sunddi.h>
+#include <sys/socket.h>
+#include <sys/neti.h>
+
+#include <netinet/in.h>
+#include <inet/common.h>
+#include <inet/mib2.h>
+#include <inet/ip.h>
+#include <inet/ip6.h>
+#include <inet/ip_if.h>
+#include <inet/ip_ire.h>
+#include <inet/ip_impl.h>
+#include <inet/ip_ndp.h>
+#include <inet/ipclassifier.h>
+#include <inet/ipp_common.h>
+#include <inet/ip_ftable.h>
+
+/*
+ * IPv4 netinfo entry point declarations.
+ */
+static int 		ip_getifname(phy_if_t, char *, const size_t);
+static int 		ip_getmtu(phy_if_t, lif_if_t);
+static int 		ip_getpmtuenabled(void);
+static int 		ip_getlifaddr(phy_if_t, lif_if_t, size_t,
+			    net_ifaddr_t [], void *);
+static phy_if_t		ip_phygetnext(phy_if_t);
+static phy_if_t 	ip_phylookup(const char *);
+static lif_if_t 	ip_lifgetnext(phy_if_t, lif_if_t);
+static int 		ip_inject(inject_t, net_inject_t *);
+static phy_if_t 	ip_routeto(struct sockaddr *);
+static int 		ip_ispartialchecksum(mblk_t *);
+static int 		ip_isvalidchecksum(mblk_t *);
+
+static int 		ipv6_getifname(phy_if_t, char *, const size_t);
+static int 		ipv6_getmtu(phy_if_t, lif_if_t);
+static int 		ipv6_getlifaddr(phy_if_t, lif_if_t, size_t,
+			    net_ifaddr_t [], void *);
+static phy_if_t 	ipv6_phygetnext(phy_if_t);
+static phy_if_t 	ipv6_phylookup(const char *);
+static lif_if_t 	ipv6_lifgetnext(phy_if_t, lif_if_t);
+static int 		ipv6_inject(inject_t, net_inject_t *);
+static phy_if_t 	ipv6_routeto(struct sockaddr *);
+static int 		ipv6_isvalidchecksum(mblk_t *);
+
+/* Netinfo private functions */
+static	int		ip_getifname_impl(phy_if_t, char *,
+			    const size_t, boolean_t);
+static	int		ip_getmtu_impl(phy_if_t, lif_if_t, boolean_t);
+static	phy_if_t	ip_phylookup_impl(const char *, boolean_t);
+static	lif_if_t	ip_lifgetnext_impl(phy_if_t, lif_if_t, boolean_t);
+static	int		ip_inject_impl(inject_t, net_inject_t *, boolean_t);
+static	int		ip_getifaddr_type(sa_family_t, ipif_t *, lif_if_t,
+			    void *);
+static	phy_if_t	ip_routeto_impl(struct sockaddr *);
+static	int		ip_getlifaddr_impl(sa_family_t, phy_if_t, lif_if_t,
+			    size_t, net_ifaddr_t [], struct sockaddr *);
+static	void		ip_ni_queue_in_func(void *);
+static	void		ip_ni_queue_out_func(void *);
+static	void		ip_ni_queue_func_impl(injection_t *,  boolean_t);
+
+
+static net_info_t ipv4info = {
+	NETINFO_VERSION,
+	NHF_INET,
+	ip_getifname,
+	ip_getmtu,
+	ip_getpmtuenabled,
+	ip_getlifaddr,
+	ip_phygetnext,
+	ip_phylookup,
+	ip_lifgetnext,
+	ip_inject,
+	ip_routeto,
+	ip_ispartialchecksum,
+	ip_isvalidchecksum
+};
+
+
+static net_info_t ipv6info = {
+	NETINFO_VERSION,
+	NHF_INET6,
+	ipv6_getifname,
+	ipv6_getmtu,
+	ip_getpmtuenabled,
+	ipv6_getlifaddr,
+	ipv6_phygetnext,
+	ipv6_phylookup,
+	ipv6_lifgetnext,
+	ipv6_inject,
+	ipv6_routeto,
+	ip_ispartialchecksum,
+	ipv6_isvalidchecksum
+};
+
+/*
+ * The taskq eventq_queue_in is used to process the upside inject messages.
+ * The taskq eventq_queue_out is used to process the downside inject messages.
+ * The taskq eventq_queue_nic is used to process the nic event messages.
+ */
+static ddi_taskq_t 	*eventq_queue_in = NULL;
+static ddi_taskq_t 	*eventq_queue_out = NULL;
+ddi_taskq_t 	*eventq_queue_nic = NULL;
+
+static hook_family_t	ipv4root;
+static hook_family_t	ipv6root;
+
+/*
+ * Hooks for firewalling
+ */
+hook_event_t		ip4_physical_in_event;
+hook_event_t		ip4_physical_out_event;
+hook_event_t		ip4_forwarding_event;
+hook_event_t		ip4_loopback_in_event;
+hook_event_t		ip4_loopback_out_event;
+hook_event_t		ip4_nic_events;
+hook_event_t		ip6_physical_in_event;
+hook_event_t		ip6_physical_out_event;
+hook_event_t		ip6_forwarding_event;
+hook_event_t		ip6_loopback_in_event;
+hook_event_t		ip6_loopback_out_event;
+hook_event_t		ip6_nic_events;
+
+hook_event_token_t	ipv4firewall_physical_in;
+hook_event_token_t	ipv4firewall_physical_out;
+hook_event_token_t	ipv4firewall_forwarding;
+hook_event_token_t	ipv4firewall_loopback_in;
+hook_event_token_t	ipv4firewall_loopback_out;
+hook_event_token_t	ipv4nicevents;
+hook_event_token_t	ipv6firewall_physical_in;
+hook_event_token_t	ipv6firewall_physical_out;
+hook_event_token_t	ipv6firewall_forwarding;
+hook_event_token_t	ipv6firewall_loopback_in;
+hook_event_token_t	ipv6firewall_loopback_out;
+hook_event_token_t	ipv6nicevents;
+
+net_data_t		ipv4 = NULL;
+net_data_t		ipv6 = NULL;
+
+
+/*
+ * Register IPv4 and IPv6 netinfo functions and initialize queues for inject.
+ */
+void
+ip_net_init()
+{
+
+	ipv4 = net_register(&ipv4info);
+	ASSERT(ipv4 != NULL);
+
+	ipv6 = net_register(&ipv6info);
+	ASSERT(ipv6 != NULL);
+
+	if (eventq_queue_out == NULL) {
+		eventq_queue_out = ddi_taskq_create(NULL,
+		    "IP_INJECT_QUEUE_OUT", 1, TASKQ_DEFAULTPRI, 0);
+
+		if (eventq_queue_out == NULL)
+			cmn_err(CE_NOTE, "ipv4_net_init: "
+			    "ddi_taskq_create failed for IP_INJECT_QUEUE_OUT");
+	}
+
+	if (eventq_queue_in == NULL) {
+		eventq_queue_in = ddi_taskq_create(NULL,
+		    "IP_INJECT_QUEUE_IN", 1, TASKQ_DEFAULTPRI, 0);
+
+		if (eventq_queue_in == NULL)
+			cmn_err(CE_NOTE, "ipv4_net_init: "
+			    "ddi_taskq_create failed for IP_INJECT_QUEUE_IN");
+	}
+
+	if (eventq_queue_nic == NULL) {
+		eventq_queue_nic = ddi_taskq_create(NULL,
+		    "IP_NIC_EVENT_QUEUE", 1, TASKQ_DEFAULTPRI, 0);
+
+		if (eventq_queue_nic == NULL)
+			cmn_err(CE_NOTE, "ipv4_net_init: "
+			    "ddi_taskq_create failed for IP_NIC_EVENT_QUEUE");
+	}
+}
+
+
+/*
+ * Unregister IPv4 and IPv6 functions and inject queues
+ */
+void
+ip_net_destroy()
+{
+
+	if (eventq_queue_nic != NULL) {
+		ddi_taskq_destroy(eventq_queue_nic);
+		eventq_queue_nic = NULL;
+	}
+
+	if (eventq_queue_in != NULL) {
+		ddi_taskq_destroy(eventq_queue_in);
+		eventq_queue_in = NULL;
+	}
+
+	if (eventq_queue_out != NULL) {
+		ddi_taskq_destroy(eventq_queue_out);
+		eventq_queue_out = NULL;
+	}
+
+	if (ipv4 != NULL) {
+		if (net_unregister(ipv4) == 0)
+			ipv4 = NULL;
+	}
+
+	if (ipv6 != NULL) {
+		if (net_unregister(ipv6) == 0)
+			ipv6 = NULL;
+	}
+}
+
+
+/*
+ * Initialize IPv4 hooks family the event
+ */
+void
+ipv4_hook_init()
+{
+
+	HOOK_FAMILY_INIT(&ipv4root, Hn_IPV4);
+	if (net_register_family(ipv4, &ipv4root) != 0) {
+		cmn_err(CE_NOTE, "ipv4_hook_init: "
+		    "net_register_family failed for ipv4");
+	}
+
+	HOOK_EVENT_INIT(&ip4_physical_in_event, NH_PHYSICAL_IN);
+	ipv4firewall_physical_in = net_register_event(ipv4,
+	    &ip4_physical_in_event);
+	if (ipv4firewall_physical_in == NULL) {
+		cmn_err(CE_NOTE, "ipv4_hook_init: "
+		    "net_register_event failed for ipv4/physical_in");
+	}
+
+	HOOK_EVENT_INIT(&ip4_physical_out_event, NH_PHYSICAL_OUT);
+	ipv4firewall_physical_out = net_register_event(ipv4,
+	    &ip4_physical_out_event);
+	if (ipv4firewall_physical_out == NULL) {
+		cmn_err(CE_NOTE, "ipv4_hook_init: "
+		    "net_register_event failed for ipv4/physical_out");
+	}
+
+	HOOK_EVENT_INIT(&ip4_forwarding_event, NH_FORWARDING);
+	ipv4firewall_forwarding = net_register_event(ipv4,
+	    &ip4_forwarding_event);
+	if (ipv4firewall_forwarding == NULL) {
+		cmn_err(CE_NOTE, "ipv4_hook_init: "
+		    "net_register_event failed for ipv4/forwarding");
+	}
+
+	HOOK_EVENT_INIT(&ip4_loopback_in_event, NH_LOOPBACK_IN);
+	ipv4firewall_loopback_in = net_register_event(ipv4,
+	    &ip4_loopback_in_event);
+	if (ipv4firewall_loopback_in == NULL) {
+		cmn_err(CE_NOTE, "ipv4_hook_init: "
+		    "net_register_event failed for ipv4/loopback_in");
+	}
+
+	HOOK_EVENT_INIT(&ip4_loopback_out_event, NH_LOOPBACK_OUT);
+	ipv4firewall_loopback_out = net_register_event(ipv4,
+	    &ip4_loopback_out_event);
+	if (ipv4firewall_loopback_out == NULL) {
+		cmn_err(CE_NOTE, "ipv4_hook_init: "
+		    "net_register_event failed for ipv4/loopback_out");
+	}
+
+	HOOK_EVENT_INIT(&ip4_nic_events, NH_NIC_EVENTS);
+	ip4_nic_events.he_flags = HOOK_RDONLY;
+	ipv4nicevents = net_register_event(ipv4, &ip4_nic_events);
+	if (ipv4nicevents == NULL) {
+		cmn_err(CE_NOTE, "ipv4_hook_init: "
+		    "net_register_event failed for ipv4/nic_events");
+	}
+}
+
+
+void
+ipv4_hook_destroy()
+{
+	if (ipv4firewall_forwarding != NULL) {
+		if (net_unregister_event(ipv4, &ip4_forwarding_event) == 0)
+			ipv4firewall_forwarding = NULL;
+	}
+
+	if (ipv4firewall_physical_in != NULL) {
+		if (net_unregister_event(ipv4, &ip4_physical_in_event) == 0)
+			ipv4firewall_physical_in = NULL;
+	}
+
+	if (ipv4firewall_physical_out != NULL) {
+		if (net_unregister_event(ipv4, &ip4_physical_out_event) == 0)
+			ipv4firewall_physical_out = NULL;
+	}
+
+	if (ipv4firewall_loopback_in != NULL) {
+		if (net_unregister_event(ipv4, &ip4_loopback_in_event) == 0)
+			ipv4firewall_loopback_in = NULL;
+	}
+
+	if (ipv4firewall_loopback_out != NULL) {
+		if (net_unregister_event(ipv4, &ip4_loopback_out_event) == 0)
+			ipv4firewall_loopback_out = NULL;
+	}
+
+	if (ipv4nicevents != NULL) {
+		if (net_unregister_event(ipv4, &ip4_nic_events) == 0)
+			ipv4nicevents = NULL;
+	}
+
+	(void) net_unregister_family(ipv4, &ipv4root);
+}
+
+
+/*
+ * Initialize IPv6 hooks family and event
+ */
+void
+ipv6_hook_init()
+{
+
+	HOOK_FAMILY_INIT(&ipv6root, Hn_IPV6);
+	if (net_register_family(ipv6, &ipv6root) != 0) {
+		cmn_err(CE_NOTE, "ipv6_hook_init: "
+		    "net_register_family failed for ipv6");
+	}
+
+	HOOK_EVENT_INIT(&ip6_physical_in_event, NH_PHYSICAL_IN);
+	ipv6firewall_physical_in = net_register_event(ipv6,
+	    &ip6_physical_in_event);
+	if (ipv6firewall_physical_in == NULL) {
+		cmn_err(CE_NOTE, "ipv6_hook_init: "
+		    "net_register_event failed for ipv6/physical_in");
+	}
+
+	HOOK_EVENT_INIT(&ip6_physical_out_event, NH_PHYSICAL_OUT);
+	ipv6firewall_physical_out = net_register_event(ipv6,
+	    &ip6_physical_out_event);
+	if (ipv6firewall_physical_out == NULL) {
+		cmn_err(CE_NOTE, "ipv6_hook_init: "
+		    "net_register_event failed for ipv6/physical_out");
+	}
+
+	HOOK_EVENT_INIT(&ip6_forwarding_event, NH_FORWARDING);
+	ipv6firewall_forwarding = net_register_event(ipv6,
+	    &ip6_forwarding_event);
+	if (ipv6firewall_forwarding == NULL) {
+		cmn_err(CE_NOTE, "ipv6_hook_init: "
+		    "net_register_event failed for ipv6/forwarding");
+	}
+
+	HOOK_EVENT_INIT(&ip6_loopback_in_event, NH_LOOPBACK_IN);
+	ipv6firewall_loopback_in = net_register_event(ipv6,
+	    &ip6_loopback_in_event);
+	if (ipv6firewall_loopback_in == NULL) {
+		cmn_err(CE_NOTE, "ipv6_hook_init: "
+		    "net_register_event failed for ipv6/loopback_in");
+	}
+
+	HOOK_EVENT_INIT(&ip6_loopback_out_event, NH_LOOPBACK_OUT);
+	ipv6firewall_loopback_out = net_register_event(ipv6,
+	    &ip6_loopback_out_event);
+	if (ipv6firewall_loopback_out == NULL) {
+		cmn_err(CE_NOTE, "ipv6_hook_init: "
+		    "net_register_event failed for ipv6/loopback_out");
+	}
+
+	HOOK_EVENT_INIT(&ip6_nic_events, NH_NIC_EVENTS);
+	ip6_nic_events.he_flags = HOOK_RDONLY;
+	ipv6nicevents = net_register_event(ipv6, &ip6_nic_events);
+	if (ipv6nicevents == NULL) {
+		cmn_err(CE_NOTE, "ipv6_hook_init: "
+		    "net_register_event failed for ipv6/nic_events");
+	}
+}
+
+
+void
+ipv6_hook_destroy()
+{
+	if (ipv6firewall_forwarding != NULL) {
+		if (net_unregister_event(ipv6, &ip6_forwarding_event) == 0)
+			ipv6firewall_forwarding = NULL;
+	}
+
+	if (ipv6firewall_physical_in != NULL) {
+		if (net_unregister_event(ipv6, &ip6_physical_in_event) == 0)
+			ipv6firewall_physical_in = NULL;
+	}
+
+	if (ipv6firewall_physical_out != NULL) {
+		if (net_unregister_event(ipv6, &ip6_physical_out_event) == 0)
+			ipv6firewall_physical_out = NULL;
+	}
+
+	if (ipv6firewall_loopback_in != NULL) {
+		if (net_unregister_event(ipv6, &ip6_loopback_in_event) == 0)
+			ipv6firewall_loopback_in = NULL;
+	}
+
+	if (ipv6firewall_loopback_out != NULL) {
+		if (net_unregister_event(ipv6, &ip6_loopback_out_event) == 0)
+			ipv6firewall_loopback_out = NULL;
+	}
+
+	if (ipv6nicevents != NULL) {
+		if (net_unregister_event(ipv6, &ip6_nic_events) == 0)
+			ipv6nicevents = NULL;
+	}
+
+	(void) net_unregister_family(ipv6, &ipv6root);
+}
+
+
+/*
+ * Determine the name of an IPv4 interface
+ */
+static int
+ip_getifname(phy_if_t phy_ifdata, char *buffer, const size_t buflen)
+{
+
+	return (ip_getifname_impl(phy_ifdata, buffer, buflen, B_FALSE));
+}
+
+
+/*
+ * Determine the name of an IPv6 interface
+ */
+static int
+ipv6_getifname(phy_if_t phy_ifdata, char *buffer, const size_t buflen)
+{
+
+	return (ip_getifname_impl(phy_ifdata, buffer, buflen, B_TRUE));
+}
+
+
+/*
+ * Shared implementation to determine the name of a given network interface
+ */
+/* ARGSUSED */
+static int
+ip_getifname_impl(phy_if_t phy_ifdata,
+    char *buffer, const size_t buflen, boolean_t isv6)
+{
+	ill_t *ill;
+
+	ASSERT(buffer != NULL);
+
+	ill = ill_lookup_on_ifindex((uint_t)phy_ifdata, isv6, NULL, NULL,
+	    NULL, NULL);
+	if (ill == NULL)
+		return (1);
+
+	if (ill->ill_name != NULL) {
+		(void) strlcpy(buffer, ill->ill_name, buflen);
+		ill_refrele(ill);
+		return (0);
+	} else {
+		ill_refrele(ill);
+		return (1);
+	}
+
+}
+
+
+/*
+ * Determine the MTU of an IPv4 network interface
+ */
+static int
+ip_getmtu(phy_if_t phy_ifdata, lif_if_t ifdata)
+{
+
+	return (ip_getmtu_impl(phy_ifdata, ifdata, B_FALSE));
+}
+
+
+/*
+ * Determine the MTU of an IPv6 network interface
+ */
+static int
+ipv6_getmtu(phy_if_t phy_ifdata, lif_if_t ifdata)
+{
+
+	return (ip_getmtu_impl(phy_ifdata, ifdata, B_TRUE));
+}
+
+
+/*
+ * Shared implementation to determine the MTU of a network interface
+ */
+/* ARGSUSED */
+static int
+ip_getmtu_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6)
+{
+	lif_if_t ipifid;
+	ipif_t *ipif;
+	int mtu;
+
+	ipifid = UNMAP_IPIF_ID(ifdata);
+
+	ipif = ipif_getby_indexes((uint_t)phy_ifdata, (uint_t)ipifid, isv6);
+	if (ipif == NULL)
+		return (0);
+
+	mtu = ipif->ipif_mtu;
+	ipif_refrele(ipif);
+
+	if (mtu == 0) {
+		ill_t *ill;
+
+		if ((ill = ill_lookup_on_ifindex((uint_t)phy_ifdata, isv6,
+		    NULL, NULL, NULL, NULL)) == NULL) {
+			return (0);
+		}
+		mtu = ill->ill_max_frag;
+		ill_refrele(ill);
+	}
+
+	return (mtu);
+}
+
+
+/*
+ * Determine if path MTU discovery is enabled for IP
+ */
+static int
+ip_getpmtuenabled(void)
+{
+
+	return (ip_path_mtu_discovery);
+}
+
+
+/*
+ * Get next interface from the current list of IPv4 physical network interfaces
+ */
+static phy_if_t
+ip_phygetnext(phy_if_t phy_ifdata)
+{
+
+	return (ill_get_next_ifindex(phy_ifdata, B_FALSE));
+}
+
+
+/*
+ * Get next interface from the current list of IPv6 physical network interfaces
+ */
+static phy_if_t
+ipv6_phygetnext(phy_if_t phy_ifdata)
+{
+
+	return (ill_get_next_ifindex(phy_ifdata, B_TRUE));
+}
+
+
+/*
+ * Determine if a network interface name exists for IPv4
+ */
+static phy_if_t
+ip_phylookup(const char *name)
+{
+
+	return (ip_phylookup_impl(name, B_FALSE));
+
+}
+
+
+/*
+ * Determine if a network interface name exists for IPv6
+ */
+static phy_if_t
+ipv6_phylookup(const char *name)
+{
+
+	return (ip_phylookup_impl(name, B_TRUE));
+}
+
+
+/*
+ * Implement looking up an ill_t based on the name supplied and matching
+ * it up with either IPv4 or IPv6.  ill_get_ifindex_by_name() is not used
+ * because it does not match on the address family in addition to the name.
+ */
+static phy_if_t
+ip_phylookup_impl(const char *name, boolean_t isv6)
+{
+	phy_if_t phy;
+	ill_t *ill;
+
+	ill = ill_lookup_on_name((char *)name, B_FALSE, isv6, NULL, NULL,
+	    NULL, NULL, NULL);
+
+	if (ill == NULL)
+		return (0);
+
+	phy = ill->ill_phyint->phyint_ifindex;
+
+	ill_refrele(ill);
+
+	return (phy);
+}
+
+
+/*
+ * Get next interface from the current list of IPv4 logical network interfaces
+ */
+static lif_if_t
+ip_lifgetnext(phy_if_t phy_ifdata, lif_if_t ifdata)
+{
+
+	return (ip_lifgetnext_impl(phy_ifdata, ifdata, B_FALSE));
+}
+
+
+/*
+ * Get next interface from the current list of IPv6 logical network interfaces
+ */
+static lif_if_t
+ipv6_lifgetnext(phy_if_t phy_ifdata, lif_if_t ifdata)
+{
+
+	return (ip_lifgetnext_impl(phy_ifdata, ifdata, B_TRUE));
+}
+
+
+/*
+ * Shared implementation to get next interface from the current list of
+ * logical network interfaces
+ */
+static lif_if_t
+ip_lifgetnext_impl(phy_if_t phy_ifdata, lif_if_t ifdata, boolean_t isv6)
+{
+	lif_if_t newidx, oldidx;
+	boolean_t nextok;
+	ipif_t *ipif;
+	ill_t *ill;
+
+	ill = ill_lookup_on_ifindex(phy_ifdata, isv6, NULL, NULL, NULL, NULL);
+	if (ill == NULL)
+		return (0);
+
+	if (ifdata != 0) {
+		oldidx = UNMAP_IPIF_ID(ifdata);
+		nextok = B_FALSE;
+	} else {
+		oldidx = 0;
+		nextok = B_TRUE;
+	}
+
+	mutex_enter(&ill->ill_lock);
+	if (ill->ill_state_flags & ILL_CONDEMNED) {
+		mutex_exit(&ill->ill_lock);
+		ill_refrele(ill);
+		return (0);
+	}
+
+	/*
+	 * It's safe to iterate the ill_ipif list when holding an ill_lock.
+	 * And it's also safe to access ipif_id without ipif refhold.
+	 * See ipif_get_id().
+	 */
+	for (ipif = ill->ill_ipif; ipif != NULL; ipif = ipif->ipif_next) {
+		if (!IPIF_CAN_LOOKUP(ipif))
+			continue;
+		if (nextok) {
+			ipif_refhold_locked(ipif);
+			break;
+		} else if (oldidx == ipif->ipif_id) {
+			nextok = B_TRUE;
+		}
+	}
+
+	mutex_exit(&ill->ill_lock);
+	ill_refrele(ill);
+
+	if (ipif == NULL)
+		return (0);
+
+	newidx = ipif->ipif_id;
+	ipif_refrele(ipif);
+
+	return (MAP_IPIF_ID(newidx));
+}
+
+
+/*
+ * Inject an IPv4 packet to or from an interface
+ */
+static int
+ip_inject(inject_t style, net_inject_t *packet)
+{
+
+	return (ip_inject_impl(style, packet, B_FALSE));
+}
+
+
+/*
+ * Inject an IPv6 packet to or from an interface
+ */
+static int
+ipv6_inject(inject_t style, net_inject_t *packet)
+{
+
+	return (ip_inject_impl(style, packet, B_TRUE));
+}
+
+
+/*
+ * Shared implementation to inject a packet to or from an interface
+ * Return value:
+ *   0: successful
+ *  -1: memory allocation failed
+ *   1: other errors
+ */
+static int
+ip_inject_impl(inject_t style, net_inject_t *packet, boolean_t isv6)
+{
+	struct sockaddr_in6 *sin6;
+	ddi_taskq_t *tq = NULL;
+	void (* func)(void*);
+	injection_t *inject;
+	ip6_t *ip6h;
+	ire_t *ire;
+	mblk_t *mp;
+
+	ASSERT(packet != NULL);
+	ASSERT(packet->ni_packet != NULL);
+	ASSERT(packet->ni_packet->b_datap->db_type == M_DATA);
+
+	switch (style) {
+	case NI_QUEUE_IN:
+		inject = kmem_alloc(sizeof (*inject), KM_NOSLEEP);
+		if (inject == NULL)
+			return (-1);
+		inject->inj_data = *packet;
+		inject->inj_isv6 = isv6;
+		/*
+		 * deliver up into the kernel, immitating its reception by a
+		 * network interface, add to list and schedule timeout
+		 */
+		func = ip_ni_queue_in_func;
+		tq = eventq_queue_in;
+		break;
+
+	case NI_QUEUE_OUT:
+		inject = kmem_alloc(sizeof (*inject), KM_NOSLEEP);
+		if (inject == NULL)
+			return (-1);
+		inject->inj_data = *packet;
+		inject->inj_isv6 = isv6;
+		/*
+		 * deliver out of the kernel, as if it were being sent via a
+		 * raw socket so that IPFilter will see it again, add to list
+		 * and schedule timeout
+		 */
+		func = ip_ni_queue_out_func;
+		tq = eventq_queue_out;
+		break;
+
+	case NI_DIRECT_OUT:
+		/*
+		 * Note:
+		 * For IPv4, the code path below will be greatly simplified
+		 * with the delivery of surya - it will become a single
+		 * function call to X.  A follow on project is aimed to
+		 * provide similar functionality for IPv6.
+		 */
+		mp = packet->ni_packet;
+
+		if (!isv6) {
+			struct sockaddr *sock;
+
+			sock = (struct sockaddr *)&packet->ni_addr;
+			/*
+			 * ipfil_sendpkt was provided by surya to ease the
+			 * problems associated with sending out a packet.
+			 * Currently this function only supports IPv4.
+			 */
+			switch (ipfil_sendpkt(sock, mp, packet->ni_physical,
+			    ALL_ZONES)) {
+			case 0 :
+			case EINPROGRESS:
+				return (0);
+			case ECOMM :
+			case ENONET :
+				return (1);
+			default :
+				return (1);
+			}
+			/* NOTREACHED */
+
+		}
+
+		ip6h = (ip6_t *)mp->b_rptr;
+		sin6 = (struct sockaddr_in6 *)&packet->ni_addr;
+		ASSERT(sin6->sin6_family == AF_INET6);
+
+		ire = ire_route_lookup_v6(&sin6->sin6_addr, 0, 0, 0,
+		    NULL, NULL, ALL_ZONES, NULL,
+		    MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE);
+
+		if (ire == NULL) {
+			ip2dbg(("ip_inject: ire_cache_lookup failed\n"));
+			freemsg(mp);
+			return (1);
+		}
+
+		if (ire->ire_stq == NULL) {
+			/* Send to loopback destination. */
+			if (ire->ire_rfq == NULL) {
+				ip2dbg(("ip_inject: bad nexthop\n"));
+				ire_refrele(ire);
+				freemsg(mp);
+				return (1);
+			}
+			ip_wput_local_v6(ire->ire_rfq,
+			    ire->ire_ipif->ipif_ill, ip6h, mp, ire, 0);
+			ire_refrele(ire);
+			return (0);
+		}
+
+		mp->b_queue = ire->ire_stq;
+
+		if (ire->ire_nce == NULL ||
+		    ire->ire_nce->nce_fp_mp == NULL &&
+		    ire->ire_nce->nce_res_mp == NULL) {
+			ip_newroute_v6(ire->ire_stq, mp,
+			    &sin6->sin6_addr, NULL, NULL, ALL_ZONES);
+
+			ire_refrele(ire);
+			return (0);
+		} else {
+			/* prepend L2 header for IPv6 packets. */
+			mblk_t *llmp;
+
+			/*
+			 * Lock IREs, see 6420438
+			 */
+			mutex_enter(&ire->ire_lock);
+			llmp = ire->ire_nce->nce_fp_mp ?
+			    ire->ire_nce->nce_fp_mp :
+			    ire->ire_nce->nce_res_mp;
+
+			if ((mp = dupb(llmp)) == NULL &&
+			    (mp = copyb(llmp)) == NULL) {
+				ip2dbg(("ip_inject: llhdr failed\n"));
+				mutex_exit(&ire->ire_lock);
+				ire_refrele(ire);
+				freemsg(mp);
+				return (1);
+			}
+			mutex_exit(&ire->ire_lock);
+			linkb(mp, packet->ni_packet);
+		}
+
+		mp->b_queue = ire->ire_stq;
+
+		break;
+	default:
+		freemsg(packet->ni_packet);
+		return (1);
+	}
+
+	if (tq) {
+		if (ddi_taskq_dispatch(tq, func, (void *)inject,
+		    DDI_SLEEP) == DDI_FAILURE) {
+			ip2dbg(("ip_inject:  ddi_taskq_dispatch failed\n"));
+			freemsg(packet->ni_packet);
+			return (1);
+		}
+	} else {
+		putnext(ire->ire_stq, mp);
+		ire_refrele(ire);
+	}
+
+	return (0);
+}
+
+
+/*
+ * Find the interface used for traffic to a given IPv4 address
+ */
+static phy_if_t
+ip_routeto(struct sockaddr *address)
+{
+
+	ASSERT(address != NULL);
+
+	if (address->sa_family != AF_INET)
+		return (0);
+	return (ip_routeto_impl(address));
+}
+
+
+/*
+ * Find the interface used for traffic to a given IPv6 address
+ */
+static phy_if_t
+ipv6_routeto(struct sockaddr *address)
+{
+
+	ASSERT(address != NULL);
+
+	if (address->sa_family != AF_INET6)
+		return (0);
+	return (ip_routeto_impl(address));
+}
+
+
+/*
+ * Find the interface used for traffic to an address
+ */
+static phy_if_t
+ip_routeto_impl(struct sockaddr *address)
+{
+	ire_t *ire;
+	ill_t *ill;
+	phy_if_t phy_if;
+
+	if (address->sa_family == AF_INET6) {
+		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)address;
+		ire = ire_route_lookup_v6(&sin6->sin6_addr, NULL,
+		    0, 0, NULL, NULL, ALL_ZONES, NULL,
+		    MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE);
+	} else {
+		struct sockaddr_in *sin = (struct sockaddr_in *)address;
+		ire = ire_route_lookup(sin->sin_addr.s_addr, 0,
+		    0, 0, NULL, NULL, ALL_ZONES, NULL,
+		    MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE);
+	}
+
+	if (ire == NULL)
+		return (0);
+
+	ill = ire_to_ill(ire);
+	if (ill == NULL)
+		return (0);
+
+	ASSERT(ill != NULL);
+	phy_if = (phy_if_t)ill->ill_phyint->phyint_ifindex;
+	ire_refrele(ire);
+
+	return (phy_if);
+}
+
+
+/*
+ * Determine if checksumming is being used for the given packet.
+ *
+ * Return value:
+ *   NET_HCK_NONE: full checksum recalculation is required
+ *   NET_HCK_L3_FULL: full layer 3 checksum
+ *   NET_HCK_L4_FULL: full layer 4 checksum
+ *   NET_HCK_L4_PART: partial layer 4 checksum
+ */
+static int
+ip_ispartialchecksum(mblk_t *mp)
+{
+	int ret = 0;
+
+	ASSERT(mp != NULL);
+
+	if ((DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM) != 0) {
+		ret |= (int)NET_HCK_L4_FULL;
+		if ((DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) != 0)
+			ret |= (int)NET_HCK_L3_FULL;
+	}
+	if ((DB_CKSUMFLAGS(mp) & HCK_PARTIALCKSUM) != 0) {
+		ret |= (int)NET_HCK_L4_PART;
+		if ((DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) != 0)
+			ret |= (int)NET_HCK_L3_FULL;
+	}
+
+	return (ret);
+}
+
+
+/*
+ * Return true or false, indicating whether the network and transport
+ * headers are correct.  Use the capabilities flags and flags set in the
+ * dblk_t to determine whether or not the checksum is valid.
+ *
+ * Return:
+ *   0: the checksum was incorrect
+ *   1: the original checksum was correct
+ */
+static int
+ip_isvalidchecksum(mblk_t *mp)
+{
+	unsigned char *wptr;
+	ipha_t *ipha = (ipha_t *)mp->b_rptr;
+	int hlen;
+	int ret;
+
+	ASSERT(mp != NULL);
+
+	if (dohwcksum &&
+	    DB_CKSUM16(mp) != 0xFFFF &&
+	    (DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM) &&
+	    (DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM_OK) &&
+	    (DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM))
+		return (1);
+
+	hlen = (ipha->ipha_version_and_hdr_length & 0x0F) << 2;
+
+	/*
+	 * Check that the mblk being passed in has enough data in it
+	 * before blindly checking ip_cksum.
+	 */
+	if (msgdsize(mp) < hlen)
+		return (0);
+
+	if (mp->b_wptr < mp->b_rptr + hlen) {
+		if (pullupmsg(mp, hlen) == 0)
+			return (0);
+		wptr = mp->b_wptr;
+	} else {
+		wptr = mp->b_wptr;
+		mp->b_wptr = mp->b_rptr + hlen;
+	}
+
+	if (ipha->ipha_hdr_checksum == ip_cksum(mp, 0, ipha->ipha_hdr_checksum))
+		ret = 1;
+	else
+		ret = 0;
+	mp->b_wptr = wptr;
+
+	return (ret);
+}
+
+
+/*
+ * Unsupported with IPv6
+ */
+/*ARGSUSED*/
+static int
+ipv6_isvalidchecksum(mblk_t *mp)
+{
+
+	return (-1);
+}
+
+/*
+ * Determine the network addresses for an IPv4 interface
+ */
+static int
+ip_getlifaddr(phy_if_t phy_ifdata, lif_if_t ifdata, size_t nelem,
+	net_ifaddr_t type[], void *storage)
+{
+
+	return (ip_getlifaddr_impl(AF_INET, phy_ifdata, ifdata,
+	    nelem, type, storage));
+}
+
+
+/*
+ * Determine the network addresses for an IPv6 interface
+ */
+static int
+ipv6_getlifaddr(phy_if_t phy_ifdata, lif_if_t ifdata, size_t nelem,
+		net_ifaddr_t type[], void *storage)
+{
+
+	return (ip_getlifaddr_impl(AF_INET6, phy_ifdata, ifdata,
+	    nelem, type, storage));
+}
+
+
+/*
+ * Shared implementation to determine the network addresses for an interface
+ */
+/* ARGSUSED */
+static int
+ip_getlifaddr_impl(sa_family_t family, phy_if_t phy_ifdata,
+    lif_if_t ifdata, size_t nelem, net_ifaddr_t type[],
+    struct sockaddr *storage)
+{
+	struct sockaddr_in6 *sin6;
+	struct sockaddr_in *sin;
+	lif_if_t ipifid;
+	ipif_t *ipif;
+	int i;
+
+	ASSERT(type != NULL);
+	ASSERT(storage != NULL);
+
+	ipifid = UNMAP_IPIF_ID(ifdata);
+
+	if (family == AF_INET) {
+		if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata,
+		    (uint_t)ipifid, B_FALSE)) == NULL)
+			return (1);
+
+		sin = (struct sockaddr_in *)storage;
+		for (i = 0; i < nelem; i++, sin++) {
+			if (ip_getifaddr_type(AF_INET, ipif, type[i],
+			    &sin->sin_addr) < 0) {
+				ip2dbg(("ip_getlifaddr_impl failed type %d\n",
+				    type[i]));
+				ipif_refrele(ipif);
+				return (1);
+			}
+		}
+	} else {
+		if ((ipif = ipif_getby_indexes((uint_t)phy_ifdata,
+		    (uint_t)ipifid, B_TRUE)) == NULL)
+			return (1);
+
+		sin6 = (struct sockaddr_in6 *)storage;
+		for (i = 0; i < nelem; i++, sin6++) {
+			if (ip_getifaddr_type(AF_INET6, ipif, type[i],
+			    &sin6->sin6_addr) < 0) {
+				ip2dbg(("ip_getlifaddr_impl failed type %d\n",
+				    type[i]));
+				ipif_refrele(ipif);
+				return (1);
+			}
+		}
+	}
+	ipif_refrele(ipif);
+	return (0);
+}
+
+/*
+ * ip_getlifaddr private function
+ */
+static int
+ip_getifaddr_type(sa_family_t family, ipif_t *ill_ipif,
+    lif_if_t type, void *storage)
+{
+	void *src_addr;
+	int mem_size;
+
+	ASSERT(ill_ipif != NULL);
+	ASSERT(storage != NULL);
+
+	if (family == AF_INET) {
+		mem_size = sizeof (struct in_addr);
+
+		switch (type) {
+		case NA_ADDRESS:
+			src_addr = &(ill_ipif->ipif_lcl_addr);
+			break;
+		case NA_PEER:
+			src_addr = &(ill_ipif->ipif_pp_dst_addr);
+			break;
+		case NA_BROADCAST:
+			src_addr = &(ill_ipif->ipif_brd_addr);
+			break;
+		case NA_NETMASK:
+			src_addr = &(ill_ipif->ipif_net_mask);
+			break;
+		default:
+			return (-1);
+			/*NOTREACHED*/
+		}
+	} else {
+		mem_size = sizeof (struct in6_addr);
+
+		switch (type) {
+		case NA_ADDRESS:
+			src_addr = &(ill_ipif->ipif_v6lcl_addr);
+			break;
+		case NA_PEER:
+			src_addr = &(ill_ipif->ipif_v6pp_dst_addr);
+			break;
+		case NA_BROADCAST:
+			src_addr = &(ill_ipif->ipif_v6brd_addr);
+			break;
+		case NA_NETMASK:
+			src_addr = &(ill_ipif->ipif_v6net_mask);
+			break;
+		default:
+			return (-1);
+			/*NOTREACHED*/
+		}
+	}
+
+	(void) memcpy(storage, src_addr, mem_size);
+	return (1);
+}
+
+
+/*
+ * Deliver packet up into the kernel, immitating its reception by a
+ * network interface.
+ */
+static void
+ip_ni_queue_in_func(void *inject)
+{
+
+	ip_ni_queue_func_impl(inject, B_FALSE);
+}
+
+
+/*
+ * Deliver out of the kernel, as if it were being sent via a
+ * raw socket so that IPFilter will see it again.
+ */
+static void
+ip_ni_queue_out_func(void *inject)
+{
+
+	ip_ni_queue_func_impl(inject, B_TRUE);
+}
+
+
+/*
+ * Shared implementation for inject via ip_output and ip_input
+ */
+static void
+ip_ni_queue_func_impl(injection_t *inject,  boolean_t out)
+{
+	net_inject_t *packet;
+	conn_t *conn;
+	ill_t *ill;
+
+	ASSERT(inject != NULL);
+	packet = &inject->inj_data;
+	ASSERT(packet->ni_packet != NULL);
+
+	if ((ill = ill_lookup_on_ifindex((uint_t)packet->ni_physical,
+	    B_FALSE, NULL, NULL, NULL, NULL)) == NULL) {
+		kmem_free(inject, sizeof (*inject));
+		return;
+	}
+
+	if (out == 0) {
+		if (inject->inj_isv6) {
+			ip_rput_v6(ill->ill_rq, packet->ni_packet);
+		} else {
+			ip_input(ill, NULL, packet->ni_packet, 0);
+		}
+		kmem_free(inject, sizeof (*inject));
+		ill_refrele(ill);
+		return;
+	}
+
+	/*
+	 * Even though ipcl_conn_create requests that it be passed
+	 * a different value for "TCP", in this case there may not
+	 * be a TCP connection backing the packet and more than
+	 * likely, non-TCP packets will go here too.
+	 */
+	conn = ipcl_conn_create(IPCL_IPCCONN, KM_NOSLEEP);
+	if (conn != NULL) {
+		if (inject->inj_isv6) {
+			conn->conn_flags |= IPCL_ISV6;
+			conn->conn_af_isv6 = B_TRUE;
+			conn->conn_src_preferences = IPV6_PREFER_SRC_DEFAULT;
+			conn->conn_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
+			ip_output_v6(conn, packet->ni_packet, ill->ill_wq,
+				IP_WPUT);
+		} else {
+			conn->conn_af_isv6 = B_FALSE;
+			conn->conn_pkt_isv6 = B_FALSE;
+			conn->conn_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
+			ip_output(conn, packet->ni_packet, ill->ill_wq,
+				IP_WPUT);
+		}
+
+		CONN_DEC_REF(conn);
+	}
+
+	kmem_free(inject, sizeof (*inject));
+	ill_refrele(ill);
+}
+
+/*
+ * taskq function for nic events.
+ */
+void
+ip_ne_queue_func(void *arg)
+{
+
+	hook_event_int_t *hr;
+	hook_nic_event_t *info = (hook_nic_event_t *)arg;
+
+	hr = (info->hne_family == ipv6) ? ipv6nicevents : ipv4nicevents;
+	(void) hook_run(hr, (hook_data_t)info);
+
+	if (info->hne_data != NULL)
+		kmem_free(info->hne_data, info->hne_datalen);
+	kmem_free(arg, sizeof (hook_nic_event_t));
+}
--- a/usr/src/uts/common/inet/ip6.h	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ip6.h	Fri Oct 20 16:37:58 2006 -0700
@@ -366,6 +366,7 @@
 extern boolean_t	ip_hdr_length_nexthdr_v6(mblk_t *, ip6_t *,
     uint16_t *, uint8_t **);
 extern int	ip_hdr_length_v6(mblk_t *, ip6_t *);
+extern int	ip_check_v6_mblk(mblk_t *, ill_t *);
 extern uint32_t	ip_massage_options_v6(ip6_t *, ip6_rthdr_t *);
 extern void	ip_wput_frag_v6(mblk_t *, ire_t *, uint_t, conn_t *, int, int);
 extern void 	ip_wput_ipsec_out_v6(queue_t *, mblk_t *, ip6_t *, ill_t *,
@@ -378,6 +379,7 @@
 extern void	ip_output_v6(void *, mblk_t *, void *, int);
 extern void	ip_xmit_v6(mblk_t *, ire_t *, uint_t, conn_t *, int,
     struct ipsec_out_s *);
+extern void	ip_rput_v6(queue_t *, mblk_t *);
 extern void	ip_rput_data_v6(queue_t *, ill_t *, mblk_t *, ip6_t *,
     uint_t, mblk_t *, mblk_t *);
 extern void	mld_input(queue_t *, mblk_t *, ill_t *);
--- a/usr/src/uts/common/inet/ip_if.h	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ip_if.h	Fri Oct 20 16:37:58 2006 -0700
@@ -164,6 +164,9 @@
     ipsq_func_t, int *);
 extern	ill_t	*ill_lookup_on_name(char *, boolean_t,
     boolean_t, queue_t *, mblk_t *, ipsq_func_t, int *, boolean_t *);
+extern uint_t	ill_get_next_ifindex(uint_t, boolean_t);
+extern uint_t	ill_get_ifindex_by_name(char *);
+extern ill_t	*ill_get_first(boolean_t isv6);
 extern	void	ill_ipif_cache_delete(ire_t *, char *);
 extern	void	ill_delete(ill_t *);
 extern	void	ill_delete_tail(ill_t *);
@@ -205,6 +208,7 @@
 extern	boolean_t ill_is_probeonly(ill_t *);
 
 extern	char	*ipif_get_name(const ipif_t *, char *, int);
+extern	ipif_t	*ipif_getby_indexes(uint_t, uint_t, boolean_t);
 extern	void	ipif_init(void);
 extern	ipif_t	*ipif_lookup_addr(ipaddr_t, ill_t *, zoneid_t, queue_t *,
     mblk_t *, ipsq_func_t, int *);
--- a/usr/src/uts/common/inet/ip_impl.h	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ip_impl.h	Fri Oct 20 16:37:58 2006 -0700
@@ -41,6 +41,8 @@
 
 #ifdef _KERNEL
 
+#include <sys/sdt.h>
+
 #define	IP_MOD_ID		5701
 
 #ifdef	_BIG_ENDIAN
@@ -480,13 +482,20 @@
  * Macro that hands off one or more messages directly to DLD
  * when the interface is marked with ILL_CAPAB_POLL.
  */
-#define	IP_DLS_ILL_TX(ill, mp) {					\
-	ill_dls_capab_t *ill_dls = ill->ill_dls_capab;		\
+#define	IP_DLS_ILL_TX(ill, ipha, mp) {					\
+	ill_dls_capab_t *ill_dls = ill->ill_dls_capab;			\
 	ASSERT(ILL_DLS_CAPABLE(ill));					\
 	ASSERT(ill_dls != NULL);					\
 	ASSERT(ill_dls->ill_tx != NULL);				\
-	ASSERT(ill_dls->ill_tx_handle != NULL);			\
-	ill_dls->ill_tx(ill_dls->ill_tx_handle, mp);			\
+	ASSERT(ill_dls->ill_tx_handle != NULL);				\
+	DTRACE_PROBE4(ip4__physical__out__start,			\
+	    ill_t *, NULL, ill_t *, ill,				\
+	    ipha_t *, ipha, mblk_t *, mp);				\
+	FW_HOOKS(ip4_physical_out_event, ipv4firewall_physical_out,	\
+	    MSG_FWCOOKED_OUT, NULL, ill, ipha, mp, mp);			\
+	DTRACE_PROBE1(ip4__physical__out__end, mblk_t *, mp);		\
+	if (mp != NULL)							\
+		ill_dls->ill_tx(ill_dls->ill_tx_handle, mp);		\
 }
 
 extern int	ip_wput_frag_mdt_min;
--- a/usr/src/uts/common/inet/ip_ire.h	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ip_ire.h	Fri Oct 20 16:37:58 2006 -0700
@@ -380,9 +380,6 @@
     boolean_t (*)(ire_t *, void *), void *);
 extern void	ire_fastpath_list_delete(ill_t *, ire_t *);
 
-extern mblk_t *ip_nexthop_route(const struct sockaddr *, char *);
-extern mblk_t *ip_nexthop(const struct sockaddr *, const char *);
-
 extern ire_t	*ire_get_next_bcast_ire(ire_t *, ire_t *);
 extern ire_t	*ire_get_next_default_ire(ire_t *, ire_t *);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/inet/ip_netinfo.h	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,52 @@
+/*
+ * 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 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_INET_IP_NETINFO_H
+#define	_INET_IP_NETINFO_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#ifdef _KERNEL
+
+extern void ip_net_init();
+extern void ip_net_destroy();
+extern void ipv4_hook_init();
+extern void ipv6_hook_init();
+extern void ipv4_hook_destroy();
+extern void ipv6_hook_destroy();
+extern void ip_ne_queue_func(void *);
+
+#endif	/* _KERNEL */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _INET_IP_NETINFO_H */
--- a/usr/src/uts/common/inet/ipf/fil.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ipf/fil.c	Fri Oct 20 16:37:58 2006 -0700
@@ -184,6 +184,9 @@
 u_long	fr_userifqs = 0;
 u_long	fr_badcoalesces[2] = {0, 0};
 u_char	ipf_iss_secret[32];
+#if SOLARIS2 >= 10
+int	ipf_loopback = 0;
+#endif
 #if defined(IPFILTER_DEFAULT_BLOCK)
 int	fr_pass = FR_BLOCK|FR_NOMATCH;
 #else
@@ -241,7 +244,9 @@
 static	int		fr_grpmapinit __P((frentry_t *fr));
 static	INLINE void	*fr_resolvelookup __P((u_int, u_int, lookupfunc_t *));
 #endif
-static	void		frsynclist __P((frentry_t *, void *));
+static	void		frsynclist __P((int, int, void *, char *, frentry_t *));
+static	void		*fr_ifsync __P((int, int, char *, char *,
+					void *, void *));
 static	ipftuneable_t	*fr_findtunebyname __P((const char *));
 static	ipftuneable_t	*fr_findtunebycookie __P((void *, void **));
 
@@ -2367,8 +2372,8 @@
 	bzero((char *)fin, sizeof(*fin));
 
 # ifdef MENTAT
-	if (qpi->qpi_flags & QF_GROUP)
-		fin->fin_flx |= FI_MBCAST;
+	if (qpi->qpi_flags & QPI_NOCKSUM)
+		fin->fin_flx |= FI_NOCKSUM;
 	m = qpi->qpi_m;
 	fin->fin_qfm = m;
 	fin->fin_qpi = qpi;
@@ -3611,10 +3616,63 @@
 
 
 /* ------------------------------------------------------------------------ */
+/* Function:    fr_ifsync                                                   */
+/* Returns:     void *    - new interface identifier                        */
+/* Parameters:  action(I)  - type of synchronisation to do                  */
+/*              v(I)       - IP version being sync'd (v4 or v6)             */
+/*              newifp(I)  - interface identifier being introduced/removed  */
+/*              oldifp(I)  - interface identifier in a filter rule          */
+/*              newname(I) - name associated with oldifp interface          */
+/*              oldname(I) - name associated with newifp interface          */
+/*                                                                          */
+/* This function returns what the new value for "oldifp" should be for its  */
+/* caller.  In some cases it will not change, in some it will.              */
+/* action == IPFSYNC_RESYNC                                                 */
+/*   a new value for oldifp will always be looked up, according to oldname, */
+/*   the values of newname and newifp are ignored.                          */
+/* action == IPFSYNC_NEWIFP                                                 */
+/*   if oldname matches newname then we are doing a sync for the matching   */
+/*   interface, so we return newifp to be used in place of oldifp.  If the  */
+/*   the names don't match, just return oldifp.                             */
+/* action == IPFSYNC_OLDIFP                                                 */
+/*   if oldifp matches newifp then we are are doing a sync to remove any    */
+/*   references to oldifp, so we return "-1".                               */
+/* ------------------------------------------------------------------------ */
+static void *fr_ifsync(action, v, newname, oldname, newifp, oldifp)
+int action, v;
+char *newname, *oldname;
+void *newifp, *oldifp;
+{
+	void *rval = oldifp;
+
+	switch (action)
+	{
+	case IPFSYNC_RESYNC :
+		if (oldname[0] != '\0') {
+			rval = fr_resolvenic(oldname, v);
+		}
+		break;
+	case IPFSYNC_NEWIFP :
+		if (!strncmp(newname, oldname, LIFNAMSIZ))
+			rval = newifp;
+		break;
+	case IPFSYNC_OLDIFP :
+		if (newifp == oldifp)
+			rval = (void *)-1;
+		break;
+	}
+
+	return rval;
+}
+
+
+/* ------------------------------------------------------------------------ */
 /* Function:    frsynclist                                                  */
 /* Returns:     void                                                        */
-/* Parameters:  fr(I)  - start of filter list to sync interface names for   */
-/*              ifp(I) - interface pointer for limiting sync lookups        */
+/* Parameters:  action(I) - type of synchronisation to do                   */
+/*              v(I)      - IP version being sync'd (v4 or v6)              */
+/*              ifp(I)    - interface identifier associated with action     */
+/*              name(I)   - name associated with ifp parameter              */
 /* Write Locks: ipf_mutex                                                   */
 /*                                                                          */
 /* Walk through a list of filter rules and resolve any interface names into */
@@ -3622,15 +3680,19 @@
 /* used in the rule.  The interface pointer is used to limit the lookups to */
 /* a specific set of matching names if it is non-NULL.                      */
 /* ------------------------------------------------------------------------ */
-static void frsynclist(fr, ifp)
+static void frsynclist(action, v, ifp, ifname, fr)
+int action, v;
+void *ifp;
+char *ifname;
 frentry_t *fr;
-void *ifp;
 {
 	frdest_t *fdp;
-	int v, i;
+	int rv, i;
 
 	for (; fr; fr = fr->fr_next) {
-		v = fr->fr_v;
+		rv = fr->fr_v;
+		if (v != 0 && v != rv)
+			continue;
 
 		/*
 		 * Lookup all the interface names that are part of the rule.
@@ -3638,42 +3700,41 @@
 		for (i = 0; i < 4; i++) {
 			if ((ifp != NULL) && (fr->fr_ifas[i] != ifp))
 				continue;
-			fr->fr_ifas[i] = fr_resolvenic(fr->fr_ifnames[i], v);
+			fr->fr_ifas[i] = fr_ifsync(action, rv, ifname,
+						   fr->fr_ifnames[i],
+						   ifp, fr->fr_ifas[i]);
 		}
 
+		fdp = &fr->fr_tifs[0];
+		fdp->fd_ifp = fr_ifsync(action, rv, ifname, fdp->fd_ifname,
+					   ifp, fdp->fd_ifp);
+
+		fdp = &fr->fr_tifs[1];
+		fdp->fd_ifp = fr_ifsync(action, rv, ifname, fdp->fd_ifname,
+					   ifp, fdp->fd_ifp);
+
+		fdp = &fr->fr_dif;
+		fdp->fd_ifp = fr_ifsync(action, rv, ifname, fdp->fd_ifname,
+					   ifp, fdp->fd_ifp);
+
+		if (action != IPFSYNC_RESYNC)
+			return;
+
 		if (fr->fr_type == FR_T_IPF) {
 			if (fr->fr_satype != FRI_NORMAL &&
 			    fr->fr_satype != FRI_LOOKUP) {
-				(void)fr_ifpaddr(v, fr->fr_satype,
+				(void)fr_ifpaddr(rv, fr->fr_satype,
 						 fr->fr_ifas[fr->fr_sifpidx],
 						 &fr->fr_src, &fr->fr_smsk);
 			}
 			if (fr->fr_datype != FRI_NORMAL &&
 			    fr->fr_datype != FRI_LOOKUP) {
-				(void)fr_ifpaddr(v, fr->fr_datype,
+				(void)fr_ifpaddr(rv, fr->fr_datype,
 						 fr->fr_ifas[fr->fr_difpidx],
 						 &fr->fr_dst, &fr->fr_dmsk);
 			}
 		}
 
-		fdp = &fr->fr_tifs[0];
-		if ((ifp == NULL) || (fdp->fd_ifp == ifp))
-			fr_resolvedest(fdp, v);
-
-		fdp = &fr->fr_tifs[1];
-		if ((ifp == NULL) || (fdp->fd_ifp == ifp))
-			fr_resolvedest(fdp, v);
-
-		fdp = &fr->fr_dif;
-		if ((ifp == NULL) || (fdp->fd_ifp == ifp)) {
-			fr_resolvedest(fdp, v);
-
-			fr->fr_flags &= ~FR_DUP;
-			if ((fdp->fd_ifp != (void *)-1) &&
-			    (fdp->fd_ifp != NULL))
-				fr->fr_flags |= FR_DUP;
-		}
-
 #ifdef	IPFILTER_LOOKUP
 		if (fr->fr_type == FR_T_IPF && fr->fr_satype == FRI_LOOKUP &&
 		    fr->fr_srcptr == NULL) {
@@ -3696,40 +3757,45 @@
 /* ------------------------------------------------------------------------ */
 /* Function:    frsync                                                      */
 /* Returns:     void                                                        */
-/* Parameters:  Nil                                                         */
+/* Parameters:  action(I) - type of synchronisation to do                   */
+/*              v(I)      - IP version being sync'd (v4 or v6)              */
+/*              ifp(I)    - interface identifier associated with action     */
+/*              name(I)   - name associated with ifp parameter              */
 /*                                                                          */
 /* frsync() is called when we suspect that the interface list or            */
 /* information about interfaces (like IP#) has changed.  Go through all     */
 /* filter rules, NAT entries and the state table and check if anything      */
 /* needs to be changed/updated.                                             */
-/* ------------------------------------------------------------------------ */
-void frsync(ifp)
+/* With the filtering hooks added to Solaris, we needed to change the manner*/
+/* in which this was done to support three different types of sync:         */
+/* - complete resync of all interface name/identifiers                      */
+/* - new interface being announced with its name and identifier             */
+/* - interface removal being announced by only its identifier               */
+/* ------------------------------------------------------------------------ */
+void frsync(action, v, ifp, name)
+int action, v;
 void *ifp;
+char *name;
 {
 	int i;
 
-# if !SOLARIS
-	fr_natsync(ifp);
-	fr_statesync(ifp);
-# endif
-
 	WRITE_ENTER(&ipf_mutex);
-	frsynclist(ipacct[0][fr_active], ifp);
-	frsynclist(ipacct[1][fr_active], ifp);
-	frsynclist(ipfilter[0][fr_active], ifp);
-	frsynclist(ipfilter[1][fr_active], ifp);
-	frsynclist(ipacct6[0][fr_active], ifp);
-	frsynclist(ipacct6[1][fr_active], ifp);
-	frsynclist(ipfilter6[0][fr_active], ifp);
-	frsynclist(ipfilter6[1][fr_active], ifp);
+	frsynclist(action, v, ifp, name, ipacct[0][fr_active]);
+	frsynclist(action, v, ifp, name, ipacct[1][fr_active]);
+	frsynclist(action, v, ifp, name, ipfilter[0][fr_active]);
+	frsynclist(action, v, ifp, name, ipfilter[1][fr_active]);
+	frsynclist(action, v, ifp, name, ipacct6[0][fr_active]);
+	frsynclist(action, v, ifp, name, ipacct6[1][fr_active]);
+	frsynclist(action, v, ifp, name, ipfilter6[0][fr_active]);
+	frsynclist(action, v, ifp, name, ipfilter6[1][fr_active]);
 
 	for (i = 0; i < IPL_LOGSIZE; i++) {
 		frgroup_t *g;
 
 		for (g = ipfgroups[i][0]; g != NULL; g = g->fg_next)
-			frsynclist(g->fg_start, ifp);
+			frsynclist(action, v, ifp, name, g->fg_start);
 		for (g = ipfgroups[i][1]; g != NULL; g = g->fg_next)
-			frsynclist(g->fg_start, ifp);
+			frsynclist(action, v, ifp, name, g->fg_start);
 	}
 	RWLOCK_EXIT(&ipf_mutex);
 }
@@ -4292,7 +4358,7 @@
 	/*
 	 * Lookup all the interface names that are part of the rule.
 	 */
-	frsynclist(fp, NULL);
+	frsynclist(0, 0, NULL, NULL, fp);
 	fp->fr_statecnt = 0;
 
 	/*
@@ -5549,6 +5615,14 @@
 	udphdr_t *udp;
 	int dosum;
 
+#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
+	net_data_t net_data_p;
+	if (fin->fin_v == 4)
+		net_data_p = ipf_ipv4;
+	else
+		net_data_p = ipf_ipv6;
+#endif
+
 	if ((fin->fin_flx & FI_NOCKSUM) != 0)
 		return 0;
 
@@ -5565,10 +5639,12 @@
 	dosum = 0;
 	sum = 0;
 
-#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_VALID)
-	if (dohwcksum && ((*fin->fin_mp)->b_ick_flag == ICK_VALID)) {
-		hdrsum = 0;
-		sum = 0;
+#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
+	ASSERT(fin->fin_m != NULL);
+	if (NET_IS_HCK_L4_FULL(net_data_p, fin->fin_m) ||
+	    NET_IS_HCK_L4_PART(net_data_p, fin->fin_m)) {
+			hdrsum = 0;
+			sum = 0;
 	} else {
 #endif
 		switch (fin->fin_p)
@@ -5602,7 +5678,7 @@
 		if (dosum)
 			sum = fr_cksum(fin->fin_m, fin->fin_ip,
 				       fin->fin_p, fin->fin_dp);
-#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_VALID)
+#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
 	}
 #endif
 #if !defined(_KERNEL)
@@ -5817,6 +5893,10 @@
 			sizeof(fr_icmpminfragmtu),	0 },
 	{ { &fr_pass },		"fr_pass",		0,	0xffffffff,
 			sizeof(fr_pass),		0 },
+#if SOLARIS2 >= 10
+	{ { &ipf_loopback},	"ipf_loopback",		0,	1,
+			sizeof(ipf_loopback),		IPFT_WRDISABLED },
+#endif
 	/* state */
 	{ { &fr_tcpidletimeout }, "fr_tcpidletimeout",	1,	0x7fffffff,
 			sizeof(fr_tcpidletimeout),	IPFT_WRDISABLED },
@@ -6338,17 +6418,13 @@
 frdest_t *fdp;
 int v;
 {
-	void *ifp;
-
-	ifp = NULL;
-	v = v;		/* LINT */
-
-	if (*fdp->fd_ifname != '\0') {
-		ifp = GETIFP(fdp->fd_ifname, v);
-		if (ifp == NULL)
-			ifp = (void *)-1;
+	fdp->fd_ifp = NULL;
+
+  	if (*fdp->fd_ifname != '\0') {
+ 		fdp->fd_ifp = GETIFP(fdp->fd_ifname, v);
+		if (fdp->fd_ifp == NULL)
+			fdp->fd_ifp = (void *)-1;
 	}
-	fdp->fd_ifp = ifp;
 }
 #endif /* _KERNEL */
 
--- a/usr/src/uts/common/inet/ipf/ip_auth.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ipf/ip_auth.c	Fri Oct 20 16:37:58 2006 -0700
@@ -3,6 +3,14 @@
  *
  * See the IPFILTER.LICENCE file for details on licencing.
  */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
 #if defined(KERNEL) || defined(_KERNEL)
 # undef KERNEL
 # undef _KERNEL
@@ -49,6 +57,7 @@
 # endif
 # include <sys/stream.h>
 # include <sys/kmem.h>
+# include <sys/neti.h>
 #endif
 #if (_BSDI_VERSION >= 199802) || (__FreeBSD_version >= 400000)
 # include <sys/queue.h>
@@ -141,6 +150,10 @@
 frentry_t	*ipauth = NULL,
 		*fr_authlist = NULL;
 
+#if SOLARIS2 >= 10
+extern net_data_t ipf_ipv4;
+extern net_data_t ipf_ipv6;
+#endif
 
 int fr_authinit()
 {
@@ -341,7 +354,6 @@
 #if SOLARIS && defined(_KERNEL)
 	m->b_rptr -= qpi->qpi_off;
 	fr_authpkts[i] = *(mblk_t **)fin->fin_mp;
-	fra->fra_q = qpi->qpi_q;	/* The queue can disappear! */
 	cv_signal(&ipfauthwait);
 #else
 # if defined(BSD) && !defined(sparc) && (BSD >= 199306)
@@ -371,6 +383,9 @@
 	frauth_t auth, *au = &auth, *fra;
 	int i, error = 0, len;
 	char *t;
+	net_data_t net_data_p;
+	net_inject_t inj_data;
+	int ret;
 
 	switch (cmd)
 	{
@@ -498,10 +513,33 @@
 		fra->fra_pass = au->fra_pass;
 		fr_authpkts[i] = NULL;
 		RWLOCK_EXIT(&ipf_auth);
+
 #ifdef	_KERNEL
+		if (fra->fra_info.fin_v == 4) { 
+			net_data_p = ipf_ipv4;
+		} else if (fra->fra_info.fin_v == 6) { 
+			net_data_p = ipf_ipv6;
+		} else { 
+			return (-1); 
+		}
+
+		/*
+		 * We're putting the packet back on the same interface
+		 * queue that it was originally seen on so that it can
+		 * progress through the system properly, with the result
+		 * of the auth check done.
+		 */
+		inj_data.ni_physical = (phy_if_t)fra->fra_info.fin_ifp;
+
 		if ((m != NULL) && (au->fra_info.fin_out != 0)) {
 # ifdef MENTAT
-			error = !putq(fra->fra_q, m);
+			inj_data.ni_packet = m;
+			ret = net_inject(net_data_p, NI_QUEUE_OUT, &inj_data);
+
+			if (ret < 0)
+				fr_authstats.fas_sendfail++;
+			else
+				fr_authstats.fas_sendok++;
 # else /* MENTAT */
 #  if defined(linux) || defined(AIX)
 #  else
@@ -513,15 +551,16 @@
 #   else
 			error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL);
 #   endif
-#  endif /* Linux */
-# endif /* MENTAT */
 			if (error != 0)
 				fr_authstats.fas_sendfail++;
 			else
 				fr_authstats.fas_sendok++;
+#  endif /* Linux */
+# endif /* MENTAT */
 		} else if (m) {
 # ifdef MENTAT
-			error = !putq(fra->fra_q, m);
+			inj_data.ni_packet = m;
+			ret = net_inject(net_data_p, NI_QUEUE_IN, &inj_data);
 # else /* MENTAT */
 #  if defined(linux) || defined(AIX)
 #  else
--- a/usr/src/uts/common/inet/ipf/ip_fil_solaris.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ipf/ip_fil_solaris.c	Fri Oct 20 16:37:58 2006 -0700
@@ -60,6 +60,7 @@
 #include <inet/ip_ire.h>
 
 #include <sys/md5.h>
+#include <sys/neti.h>
 
 extern	int	fr_flags, fr_active;
 #if SOLARIS2 >= 7
@@ -67,9 +68,36 @@
 #else
 int	fr_timer_id;
 #endif
+#if SOLARIS2 >= 10
+extern	int	ipf_loopback;
+#endif
 
 
+static	int	fr_setipfloopback __P((int));
 static	int	fr_send_ip __P((fr_info_t *fin, mblk_t *m, mblk_t **mp));
+static	int	ipf_nic_event_v4 __P((hook_event_token_t, hook_data_t));
+static	int	ipf_nic_event_v6 __P((hook_event_token_t, hook_data_t));
+static	int	ipf_hook_out __P((hook_event_token_t, hook_data_t));
+static	int	ipf_hook_in __P((hook_event_token_t, hook_data_t));
+static	int	ipf_hook_loop_out __P((hook_event_token_t, hook_data_t));
+static	int	ipf_hook_loop_in __P((hook_event_token_t, hook_data_t));
+static	int	ipf_hook __P((hook_data_t, int, int));
+
+static	hook_t	ipfhook_in;
+static	hook_t	ipfhook_out;
+static	hook_t	ipfhook_nicevents;
+
+/* flags to indicate whether hooks are registered. */
+static	boolean_t	hook4_physical_in	= B_FALSE;
+static	boolean_t	hook4_physical_out	= B_FALSE;
+static	boolean_t	hook4_nic_events	= B_FALSE;
+static	boolean_t	hook4_loopback_in	= B_FALSE;
+static	boolean_t	hook4_loopback_out	= B_FALSE;
+static	boolean_t	hook6_physical_in	= B_FALSE;
+static	boolean_t	hook6_physical_out	= B_FALSE;
+static	boolean_t	hook6_nic_events	= B_FALSE;
+static	boolean_t	hook6_loopback_in	= B_FALSE;
+static	boolean_t	hook6_loopback_out	= B_FALSE;
 
 ipfmutex_t	ipl_mutex, ipf_authmx, ipf_rw, ipf_stinsert;
 ipfmutex_t	ipf_nat_new, ipf_natio, ipf_timeoutlock;
@@ -94,6 +122,10 @@
 u_long		*ip_forwarding = NULL;
 #endif
 #endif
+#if SOLARIS2 >= 10
+extern net_data_t ipf_ipv4;
+extern net_data_t ipf_ipv6;
+#endif
 int		ipf_locks_done = 0;
 
 
@@ -125,10 +157,79 @@
 	}
 #endif
 
+	/*
+	 * This lock needs to be dropped around the net_unregister_hook calls
+	 * because we can deadlock here with:
+	 * W(ipf_global)->R(hook_family)->W(hei_lock) (this code path) vs
+	 * R(hook_family)->R(hei_lock)->R(ipf_global) (active hook running)
+	 */
+	RWLOCK_EXIT(&ipf_global);
+
+	/*
+	 * Remove IPv6 Hooks
+	 */
+	if (ipf_ipv6 != NULL) {
+		if (hook6_physical_in) {
+			hook6_physical_in = (net_unregister_hook(ipf_ipv6,
+			    NH_PHYSICAL_IN, &ipfhook_in) != 0);
+		}
+		if (hook6_physical_out) {
+			hook6_physical_out = (net_unregister_hook(ipf_ipv6,
+			    NH_PHYSICAL_OUT, &ipfhook_out) != 0);
+		}
+		if (hook6_nic_events) {
+			hook6_nic_events = (net_unregister_hook(ipf_ipv6,
+			    NH_NIC_EVENTS, &ipfhook_nicevents) != 0);
+		}
+		if (hook6_loopback_in) {
+			hook6_loopback_in = (net_unregister_hook(ipf_ipv6,
+			    NH_LOOPBACK_IN, &ipfhook_in) != 0);
+		}
+		if (hook6_loopback_out) {
+			hook6_loopback_out = (net_unregister_hook(ipf_ipv6,
+			    NH_LOOPBACK_OUT, &ipfhook_out) != 0);
+		}
+
+		if (net_release(ipf_ipv6) != 0)
+			goto detach_failed;
+		ipf_ipv6 = NULL;
+        }
+
+	/*
+	 * Remove IPv4 Hooks
+	 */
+	if (ipf_ipv4 != NULL) {
+		if (hook4_physical_in) {
+			hook4_physical_in = (net_unregister_hook(ipf_ipv4,
+			    NH_PHYSICAL_IN, &ipfhook_in) != 0);
+		}
+		if (hook4_physical_out) {
+			hook4_physical_out = (net_unregister_hook(ipf_ipv4,
+			    NH_PHYSICAL_OUT, &ipfhook_out) != 0);
+		}
+		if (hook4_nic_events) {
+			hook4_nic_events = (net_unregister_hook(ipf_ipv4,
+			    NH_NIC_EVENTS, &ipfhook_nicevents) != 0);
+		}
+		if (hook4_loopback_in) {
+			hook4_loopback_in = (net_unregister_hook(ipf_ipv4,
+			    NH_LOOPBACK_IN, &ipfhook_in) != 0);
+		}
+		if (hook4_loopback_out) {
+			hook4_loopback_out = (net_unregister_hook(ipf_ipv4,
+			    NH_LOOPBACK_OUT, &ipfhook_out) != 0);
+		}
+
+		if (net_release(ipf_ipv4) != 0)
+			goto detach_failed;
+		ipf_ipv4 = NULL;
+	}
+
 #ifdef	IPFDEBUG
 	cmn_err(CE_CONT, "ipldetach()\n");
 #endif
 
+	WRITE_ENTER(&ipf_global);
 	fr_deinitialise();
 
 	(void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE);
@@ -140,7 +241,18 @@
 		RW_DESTROY(&ipf_ipidfrag);
 		ipf_locks_done = 0;
 	}
+
+	if (hook4_physical_in || hook4_physical_out || hook4_nic_events ||
+	    hook4_loopback_in || hook4_loopback_out || hook6_nic_events ||
+	    hook6_physical_in || hook6_physical_out || hook6_loopback_in ||
+	    hook6_loopback_out)
+		return -1;
+
 	return 0;
+
+detach_failed:
+	WRITE_ENTER(&ipf_global);
+	return -1;
 }
 
 
@@ -165,6 +277,101 @@
 	if (fr_initialise() < 0)
 		return -1;
 
+	HOOK_INIT(&ipfhook_nicevents, ipf_nic_event_v4,
+		  "ipfilter_hook_nicevents");
+	HOOK_INIT(&ipfhook_in, ipf_hook_in, "ipfilter_hook_in");
+	HOOK_INIT(&ipfhook_out, ipf_hook_out, "ipfilter_hook_out");
+
+	/*
+	 * If we hold this lock over all of the net_register_hook calls, we
+	 * can cause a deadlock to occur with the following lock ordering:
+	 * W(ipf_global)->R(hook_family)->W(hei_lock) (this code path) vs
+	 * R(hook_family)->R(hei_lock)->R(ipf_global) (packet path)
+	 */
+	RWLOCK_EXIT(&ipf_global);
+
+	/*
+	 * Add IPv4 hooks
+	 */
+	ipf_ipv4 = net_lookup(NHF_INET);
+	if (ipf_ipv4 == NULL)
+		goto hookup_failed;
+
+	hook4_nic_events = (net_register_hook(ipf_ipv4, NH_NIC_EVENTS,
+	    &ipfhook_nicevents) == 0);
+	if (!hook4_nic_events)
+		goto hookup_failed;
+
+	ipfhook_in.h_func = ipf_hook_in;
+	hook4_physical_in = (net_register_hook(ipf_ipv4, NH_PHYSICAL_IN,
+	    &ipfhook_in) == 0);
+	if (!hook4_physical_in)
+		goto hookup_failed;
+
+	ipfhook_in.h_func = ipf_hook_out;
+	hook4_physical_out = (net_register_hook(ipf_ipv4, NH_PHYSICAL_OUT,
+	    &ipfhook_out) == 0);
+	if (!hook4_physical_out)
+		goto hookup_failed;
+
+	if (ipf_loopback) {
+		ipfhook_in.h_func = ipf_hook_loop_in;
+		hook4_loopback_in = (net_register_hook(ipf_ipv4,
+		    NH_LOOPBACK_IN, &ipfhook_in) == 0);
+		if (!hook4_loopback_in)
+			goto hookup_failed;
+
+		ipfhook_in.h_func = ipf_hook_loop_out;
+		hook4_loopback_out = (net_register_hook(ipf_ipv4,
+		    NH_LOOPBACK_OUT, &ipfhook_out) == 0);
+		if (!hook4_loopback_out)
+			goto hookup_failed;
+	}
+	/*
+	 * Add IPv6 hooks
+	 */
+	ipf_ipv6 = net_lookup(NHF_INET6);
+	if (ipf_ipv6 == NULL)
+		goto hookup_failed;
+
+	HOOK_INIT(&ipfhook_nicevents, ipf_nic_event_v6,
+		  "ipfilter_hook_nicevents");
+	hook6_nic_events = (net_register_hook(ipf_ipv6, NH_NIC_EVENTS,
+	    &ipfhook_nicevents) == 0);
+	if (!hook6_nic_events)
+		goto hookup_failed;
+
+	ipfhook_in.h_func = ipf_hook_in;
+	hook6_physical_in = (net_register_hook(ipf_ipv6, NH_PHYSICAL_IN,
+	    &ipfhook_in) == 0);
+	if (!hook6_physical_in)
+		goto hookup_failed;
+
+	ipfhook_in.h_func = ipf_hook_out;
+	hook6_physical_out = (net_register_hook(ipf_ipv6, NH_PHYSICAL_OUT,
+	    &ipfhook_out) == 0);
+	if (!hook6_physical_out)
+		goto hookup_failed;
+
+	if (ipf_loopback) {
+		ipfhook_in.h_func = ipf_hook_loop_in;
+		hook6_loopback_in = (net_register_hook(ipf_ipv6,
+		    NH_LOOPBACK_IN, &ipfhook_in) == 0);
+		if (!hook6_loopback_in)
+			goto hookup_failed;
+
+		ipfhook_in.h_func = ipf_hook_loop_out;
+		hook6_loopback_out = (net_register_hook(ipf_ipv6,
+		    NH_LOOPBACK_OUT, &ipfhook_out) == 0);
+		if (!hook6_loopback_out)
+			goto hookup_failed;
+	}
+
+	/*
+	 * Reacquire ipf_global, now it is safe.
+	 */
+	WRITE_ENTER(&ipf_global);
+
 /* Do not use private interface ip_params_arr[] in Solaris 10 */
 #if SOLARIS2 < 10
 
@@ -218,6 +425,64 @@
 #endif
 
 	return 0;
+hookup_failed:
+	WRITE_ENTER(&ipf_global);
+	return -1;
+}
+
+static	int	fr_setipfloopback(set)
+int set;
+{
+	if (ipf_ipv4 == NULL || ipf_ipv6 == NULL)
+		return EFAULT;
+
+	if (set && !ipf_loopback) {
+		ipf_loopback = 1;
+
+		hook4_loopback_in = (net_register_hook(ipf_ipv4,
+		    NH_LOOPBACK_IN, &ipfhook_in) == 0);
+		if (!hook4_loopback_in)
+			return EINVAL;
+
+		hook4_loopback_out = (net_register_hook(ipf_ipv4,
+		    NH_LOOPBACK_OUT, &ipfhook_out) == 0);
+		if (!hook4_loopback_out)
+			return EINVAL;
+
+		hook6_loopback_in = (net_register_hook(ipf_ipv6,
+		    NH_LOOPBACK_IN, &ipfhook_in) == 0);
+		if (!hook6_loopback_in)
+			return EINVAL;
+
+		hook6_loopback_out = (net_register_hook(ipf_ipv6,
+		    NH_LOOPBACK_OUT, &ipfhook_out) == 0);
+		if (!hook6_loopback_out)
+			return EINVAL;
+
+	} else if (!set && ipf_loopback) {
+		ipf_loopback = 0;
+
+		hook4_loopback_in = (net_unregister_hook(ipf_ipv4,
+		    NH_LOOPBACK_IN, &ipfhook_in) != 0);
+		if (hook4_loopback_in)
+			return EBUSY;
+
+		hook4_loopback_out = (net_unregister_hook(ipf_ipv4,
+		    NH_LOOPBACK_OUT, &ipfhook_out) != 0);
+		if (hook4_loopback_out)
+			return EBUSY;
+
+		hook6_loopback_in = (net_unregister_hook(ipf_ipv6,
+		    NH_LOOPBACK_IN, &ipfhook_in) != 0);
+		if (hook6_loopback_in)
+			return EBUSY;
+
+		hook6_loopback_out = (net_unregister_hook(ipf_ipv6,
+		    NH_LOOPBACK_OUT, &ipfhook_out) != 0);
+		if (hook6_loopback_out)
+			return EBUSY;
+	}
+	return 0;
 }
 
 
@@ -319,6 +584,14 @@
 				error = EFAULT;
 		}
 		break;
+	case SIOCIPFLP :
+		error = COPYIN((caddr_t)data, (caddr_t)&tmp,
+			       sizeof(tmp));
+		if (error != 0)
+			error = EFAULT;
+		else
+			error = fr_setipfloopback(tmp);
+		break;
 	case SIOCGETFF :
 		error = COPYOUT((caddr_t)&fr_flags, (caddr_t)data,
 			       sizeof(fr_flags));
@@ -435,7 +708,12 @@
 		else {
 			RWLOCK_EXIT(&ipf_global);
 			WRITE_ENTER(&ipf_global);
-			error = ipfsync();
+
+			frsync(IPFSYNC_RESYNC, 0, NULL, NULL);
+			fr_natifpsync(IPFSYNC_RESYNC, NULL, NULL);
+			fr_nataddrsync(NULL, NULL);
+			fr_statesync(IPFSYNC_RESYNC, 0, NULL, NULL);
+			error = 0;
 		}
 		break;
 	case SIOCGFRST :
@@ -461,26 +739,25 @@
 }
 
 
-void	*get_unit(name, v)
-char	*name;
-int	v;
+phy_if_t	get_unit(name, v)
+char		*name;
+int    		v;
 {
-	qif_t *qf;
-	int sap;
+	phy_if_t phy;
+	net_data_t nif;
+ 
+  	if (v == 4)
+ 		nif = ipf_ipv4;
+  	else if (v == 6)
+ 		nif = ipf_ipv6;
+  	else
+ 		return 0;
+  
+ 	phy = net_phylookup(nif, name);
 
-	if (v == 4)
-		sap = 0x0800;
-	else if (v == 6)
-		sap = 0x86dd;
-	else
-		return NULL;
-	rw_enter(&pfil_rw, RW_READER);
-	qf = qif_iflookup(name, sap);
-	rw_exit(&pfil_rw);
-	return qf;
+ 	return (phy);
 }
 
-
 /*
  * routines below for saving IP headers to buffer
  */
@@ -675,7 +952,6 @@
 {
 	qpktinfo_t qpi, *qpip;
 	fr_info_t fnew;
-	qif_t *qif;
 	ip_t *ip;
 	int i, hlen;
 
@@ -698,8 +974,8 @@
 		fnew.fin_v = 4;
 #if SOLARIS2 >= 10
 		ip->ip_ttl = 255;
-
-		ip->ip_off = htons(IP_DF);
+		if (net_getpmtuenabled(ipf_ipv4) == 1)
+			ip->ip_off = htons(IP_DF);
 #else
 		if (ip_ttl_ptr != NULL)
 			ip->ip_ttl = (u_char)(*ip_ttl_ptr);
@@ -724,17 +1000,8 @@
 	}
 
 	qpip = fin->fin_qpi;
-	qpi.qpi_q = qpip->qpi_q;
 	qpi.qpi_off = 0;
-	qpi.qpi_name = qpip->qpi_name;
-	qif = qpip->qpi_real;
-	qpi.qpi_real = qif;
-	qpi.qpi_ill = qif->qf_ill;
-	qpi.qpi_hl = qif->qf_hl;
-	qpi.qpi_ppa = qif->qf_ppa;
-	qpi.qpi_num = qif->qf_num;
-	qpi.qpi_flags = qif->qf_flags;
-	qpi.qpi_max_frag = qif->qf_max_frag;
+	qpi.qpi_ill = qpip->qpi_ill;
 	qpi.qpi_m = m;
 	qpi.qpi_data = ip;
 	fnew.fin_qpi = &qpi;
@@ -761,6 +1028,7 @@
 	struct icmp *icmp;
 	qpktinfo_t *qpi;
 	int hlen, code;
+	phy_if_t phy;
 	u_short sz;
 #ifdef	USE_INET6
 	mblk_t *mb;
@@ -830,11 +1098,10 @@
 	icmp = (struct icmp *)(m->b_rptr + hlen);
 	icmp->icmp_type = type & 0xff;
 	icmp->icmp_code = code & 0xff;
-#ifdef	icmp_nextmtu
-	if (type == ICMP_UNREACH && (qpi->qpi_max_frag != 0) &&
+	phy = (phy_if_t)qpi->qpi_ill; 
+	if (type == ICMP_UNREACH && (phy != 0) && 
 	    fin->fin_icode == ICMP_UNREACH_NEEDFRAG)
-		icmp->icmp_nextmtu = htons(qpi->qpi_max_frag);
-#endif
+		icmp->icmp_nextmtu = net_getmtu(ipf_ipv4, phy,0 );
 
 #ifdef	USE_INET6
 	if (fin->fin_v == 6) {
@@ -842,8 +1109,8 @@
 		int csz;
 
 		if (dst == 0) {
-			if (fr_ifpaddr(6, FRI_NORMAL, qpi->qpi_real,
-				       (struct in_addr *)&dst6, NULL) == -1) {
+			if (fr_ifpaddr(6, FRI_NORMAL, (void *)phy,
+				       (void *)&dst6, NULL) == -1) {
 				FREE_MB_T(m);
 				return -1;
 			}
@@ -870,13 +1137,14 @@
 		ip->ip_tos = fin->fin_ip->ip_tos;
 		ip->ip_len = (u_short)sz;
 		if (dst == 0) {
-			if (fr_ifpaddr(4, FRI_NORMAL, qpi->qpi_real,
-				       &dst4, NULL) == -1) {
+			if (fr_ifpaddr(4, FRI_NORMAL, (void *)phy,
+				       (void *)&dst4, NULL) == -1) {
 				FREE_MB_T(m);
 				return -1;
 			}
-		} else
+		} else {
 			dst4 = fin->fin_dst;
+		}
 		ip->ip_src = dst4;
 		ip->ip_dst = fin->fin_src;
 		bcopy((char *)fin->fin_ip, (char *)&icmp->icmp_ip,
@@ -896,7 +1164,6 @@
 	return fr_send_ip(fin, m, &m);
 }
 
-#ifdef IRE_ILL_CN
 #include <sys/time.h>
 #include <sys/varargs.h>
 
@@ -940,120 +1207,68 @@
 #endif
 	}
 }
-#endif
 
 /*
  * return the first IP Address associated with an interface
  */
 /*ARGSUSED*/
-int fr_ifpaddr(v, atype, qifptr, inp, inpmask)
+int fr_ifpaddr(v, atype, ifptr, inp, inpmask)
 int v, atype;
-void *qifptr;
-struct in_addr *inp, *inpmask;
+void *ifptr;
+struct in_addr  *inp, *inpmask;
 {
-#ifdef	USE_INET6
-	struct sockaddr_in6 sin6, mask6;
-#endif
-	struct sockaddr_in sin, mask;
-	qif_t *qif;
+	struct sockaddr_in6 v6addr[2];
+	struct sockaddr_in v4addr[2];
+	net_ifaddr_t type[2];
+	net_data_t net_data;
+	phy_if_t phyif;
+	void *array;
 
-#ifdef	USE_INET6
-#ifdef IRE_ILL_CN
-	s_ill_t *ill;
-#endif
-#endif
-	if ((qifptr == NULL) || (qifptr == (void *)-1))
+	switch (v)
+	{
+	case 4:
+		net_data = ipf_ipv4;
+		array = v4addr;
+		break;
+	case 6:
+		net_data = ipf_ipv6;
+		array = v6addr;
+		break;
+	default:
+		net_data = NULL;
+		break;
+	}
+
+	if (net_data == NULL)
 		return -1;
 
-	qif = qifptr;
-
-#ifdef	USE_INET6
-#ifdef IRE_ILL_CN
-	ill = qif->qf_ill;
-#endif
-#endif
-
-#ifdef	USE_INET6
-	if (v == 6) {
-#ifndef	IRE_ILL_CN
-		in6_addr_t *inp6;
-		ipif_t *ipif;
-		ill_t *ill;
-
-		ill = qif->qf_ill;
-
-		/*
-		 * First is always link local.
-		 */
-		for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
-			inp6 = &ipif->ipif_v6lcl_addr;
-			if (!IN6_IS_ADDR_LINKLOCAL(inp6) &&
-			    !IN6_IS_ADDR_LOOPBACK(inp6))
-				break;
-		}
-		if (ipif == NULL)
-			return -1;
-
-		mask6.sin6_addr = ipif->ipif_v6net_mask;
-		if (atype == FRI_BROADCAST)
-			sin6.sin6_addr = ipif->ipif_v6brd_addr;
-		else if (atype == FRI_PEERADDR)
-			sin6.sin6_addr = ipif->ipif_v6pp_dst_addr;
-		else
-			sin6.sin6_addr = *inp6;
-#else /* IRE_ILL_CN */
-		if (IN6_IS_ADDR_UNSPECIFIED(&ill->netmask.in6.sin6_addr) ||
-		    IN6_IS_ADDR_UNSPECIFIED(&ill->localaddr.in6.sin6_addr)) {
-			rate_limit_message(NULLADDR_RATE_LIMIT,
-			   "Check pfild is running: IP#/netmask is 0 on %s.\n",
-			   ill->ill_name);
-			return -1;
-		}
-		mask6 = ill->netmask.in6;
-		if (atype == FRI_BROADCAST)
-			sin6 = ill->broadaddr.in6;
-		else if (atype == FRI_PEERADDR)
-			sin6 = ill->dstaddr.in6;
-		else
-			sin6 = ill->localaddr.in6;
-#endif /* IRE_ILL_CN */
-		return fr_ifpfillv6addr(atype, &sin6, &mask6, inp, inpmask);
-	}
-#endif
-
-#ifndef	IRE_ILL_CN
+	phyif = (phy_if_t)ifptr;
 
 	switch (atype)
 	{
-	case FRI_BROADCAST :
-		sin.sin_addr.s_addr = QF_V4_BROADCAST(qif);
+	case FRI_PEERADDR :
+		type[0] = NA_PEER;
 		break;
-	case FRI_PEERADDR :
-		sin.sin_addr.s_addr = QF_V4_PEERADDR(qif);
+
+	case FRI_BROADCAST :
+		type[0] = NA_BROADCAST;
 		break;
+
 	default :
-		sin.sin_addr.s_addr = QF_V4_ADDR(qif);
+		type[0] = NA_ADDRESS;
 		break;
 	}
-	mask.sin_addr.s_addr = QF_V4_NETMASK(qif);
+
+	type[1] = NA_NETMASK;
 
-#else
-	if (ill->netmask.in.sin_addr.s_addr == 0 ||
-		ill->localaddr.in.sin_addr.s_addr == 0) {
-		rate_limit_message(NULLADDR_RATE_LIMIT,
-			"Check pfild is running: IP#/netmask is 0 on %s.\n",
-			ill->ill_name);
+	if (net_getlifaddr(net_data, phyif, 0, 2, type, array) < 0)
 		return -1;
+
+	if (v == 6) {
+		return fr_ifpfillv6addr(atype, &v6addr[0], &v6addr[1],
+					inp, inpmask);
 	}
-	mask = ill->netmask.in;
-	if (atype == FRI_BROADCAST)
-		sin = ill->broadaddr.in;
-	else if (atype == FRI_PEERADDR)
-		sin = ill->dstaddr.in;
-	else
-		sin = ill->localaddr.in;
-#endif /* IRE_ILL_CN */
-	return fr_ifpfillv4addr(atype, &sin, &mask, inp, inpmask);
+	return fr_ifpfillv4addr(atype, &v4addr[0], &v4addr[1], inp, inpmask);
 }
 
 
@@ -1154,42 +1369,6 @@
 #endif /* USE_INET6 */
 
 
-/*
- * Function:    fr_verifysrc
- * Returns:     int (really boolean)
- * Parameters:  fin - packet information
- *
- * Check whether the packet has a valid source address for the interface on
- * which the packet arrived, implementing the "fr_chksrc" feature.
- * Returns true iff the packet's source address is valid.
- * Pre-Solaris 10, we call into the routing code to make the determination.
- * On Solaris 10 and later, we have a valid address set from pfild to check
- * against.
- */
-int fr_verifysrc(fin)
-fr_info_t *fin;
-{
-	ire_t *dir;
-	int result;
-
-#if SOLARIS2 >= 6
-	dir = ire_route_lookup(fin->fin_saddr, 0xffffffff, 0, 0, NULL,
-			       NULL, NULL, NULL, MATCH_IRE_DSTONLY|
-				MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE);
-#else
-	dir = ire_lookup(fin->fin_saddr);
-#endif
-
-	if (!dir)
-		return 0;
-	result = (ire_to_ill(dir) == fin->fin_ifp);
-#if SOLARIS2 >= 8
-	ire_refrele(dir);
-#endif
-	return result;
-}
-
-
 #if (SOLARIS2 < 7)
 void fr_slowtimer()
 #else
@@ -1223,330 +1402,6 @@
 }
 
 
-/*
- * Function:  fr_fastroute
- * Returns:    0: success;
- *            -1: failed
- * Parameters:
- *    mb: the message block where ip head starts
- *    mpp: the pointer to the pointer of the orignal
- *            packet message
- *    fin: packet information
- *    fdp: destination interface information
- *    if it is NULL, no interface information provided.
- *
- * This function is for fastroute/to/dup-to rules. It calls
- * pfil_make_lay2_packet to search route, make lay-2 header
- * ,and identify output queue for the IP packet.
- * The destination address depends on the following conditions:
- * 1: for fastroute rule, fdp is passed in as NULL, so the
- *    destination address is the IP Packet's destination address
- * 2: for to/dup-to rule, if an ip address is specified after
- *    the interface name, this address is the as destination
- *    address. Otherwise IP Packet's destination address is used
- */
-int fr_fastroute(mb, mpp, fin, fdp)
-mblk_t *mb, **mpp;
-fr_info_t *fin;
-frdest_t *fdp;
-{
-	struct in_addr dst;
-#ifndef IRE_ILL_CN
-	size_t hlen = 0;
-	ill_t *ifp;
-	ire_t *dir;
-	u_char *s;
-	frdest_t fd;
-#ifdef	USE_INET6
-	ip6_t *ip6 = (ip6_t *)fin->fin_ip;
-#endif
-#else
-	void *target = NULL;
-	char *ifname = NULL;
-#endif
-	queue_t *q = NULL;
-	mblk_t *mp = NULL;
-	qpktinfo_t *qpi;
-	frentry_t *fr;
-	qif_t *qif;
-	ip_t *ip;
-#ifndef	sparc
-	u_short __iplen, __ipoff;
-#endif
-#ifdef	USE_INET6
-	struct in6_addr dst6;
-#endif
-#ifndef IRE_ILL_CN
-	dir = NULL;
-#endif
-	fr = fin->fin_fr;
-	ip = fin->fin_ip;
-	qpi = fin->fin_qpi;
-
-	/*
-	 * If this is a duplicate mblk then we want ip to point at that
-	 * data, not the original, if and only if it is already pointing at
-	 * the current mblk data.
-	 * Otherwise, If it's not a duplicate, and we're not already pointing
-	 * at the current mblk data, then we want to ensure that the data
-	 * points at ip.
-	 */
-	if (ip == (ip_t *)qpi->qpi_m->b_rptr && qpi->qpi_m != mb)
-		ip = (ip_t *)mb->b_rptr;
-	else if (qpi->qpi_m == mb && ip != (ip_t *)qpi->qpi_m->b_rptr) {
-		qpi->qpi_m->b_rptr = (u_char *)ip;
-		qpi->qpi_off = 0;
-	}
-
-	/*
-	 * If there is another M_PROTO, we don't want it
-	 */
-	if (*mpp != mb) {
-		mp = unlinkb(*mpp);
-		freeb(*mpp);
-		*mpp = mp;
-	}
-
-	/*
-	 * If the fdp is NULL then there is no set route for this packet.
-	 */
-	if (fdp == NULL) {
-		qif = fin->fin_ifp;
-#ifndef IRE_ILL_CN
-		switch (fin->fin_v)
-		{
-		case 4 :
-			fd.fd_ip = ip->ip_dst;
-			break;
-#ifdef USE_INET6
-		case 6 :
-			fd.fd_ip6.in6 = ip6->ip6_dst;
-			break;
-#endif
-		}
-		fdp = &fd;
-#endif
-	} else {
-		qif = fdp->fd_ifp;
-
-		if (qif == NULL || qif == (void *)-1)
-			goto bad_fastroute;
-	}
-
-	/*
-	 * In case we're here due to "to <if>" being used with
-	 * "keep state", check that we're going in the correct
-	 * direction.
-	 */
-	if ((fr != NULL) && (fin->fin_rev != 0)) {
-		if ((qif != NULL) && (fdp == &fr->fr_tif))
-			return -1;
-		dst.s_addr = fin->fin_fi.fi_daddr;
-	} else {
-		if (fin->fin_v == 4) {
-			if (fdp && fdp->fd_ip.s_addr != 0) {
-				dst = fdp->fd_ip;
-#ifdef IRE_ILL_CN
-				target = &dst;
-#endif
-			} else
-				dst.s_addr = fin->fin_fi.fi_daddr;
-		}
-#ifdef USE_INET6
-		else if (fin->fin_v == 6) {
-			if (fdp && IP6_NOTZERO(&fdp->fd_ip)) {
-				dst6 = fdp->fd_ip6.in6;
-#ifdef IRE_ILL_CN
-				target = &dst6;
-#endif
-			} else
-				dst6 = fin->fin_dst6;
-		}
-#endif
-		else
-			goto bad_fastroute;
-	}
-
-#ifndef IRE_ILL_CN
-#if SOLARIS2 >= 6
-	if (fin->fin_v == 4) {
-		dir = ire_route_lookup(dst.s_addr, 0xffffffff, 0, 0, NULL,
-					NULL, NULL, MATCH_IRE_DSTONLY|
-					MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE);
-	}
-# ifdef	USE_INET6
-	else if (fin->fin_v == 6) {
-		dir = ire_route_lookup_v6(&ip6->ip6_dst, NULL, 0, 0,
-					NULL, NULL, NULL, MATCH_IRE_DSTONLY|
-					MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE);
-	}
-# endif
-#else
-	dir = ire_lookup(dst.s_addr);
-#endif
-#if SOLARIS2 < 8
-	if (dir != NULL)
-		if (dir->ire_ll_hdr_mp == NULL || dir->ire_ll_hdr_length == 0)
-			dir = NULL;
-
-#elif (SOLARIS2 >= 8) && (SOLARIS2 <= 10)
-	if (dir != NULL) {
-		if (dir->ire_fp_mp == NULL || dir->ire_dlureq_mp == NULL) {
-			ire_refrele(dir);
-			dir = NULL;
-		}
-	}
-#else
-
-	if (dir != NULL)
-		if (dir->ire_nce && dir->ire_nce->nce_state != ND_REACHABLE) {
-			ire_refrele(dir);
-			dir = NULL;
-		}
-#endif
-#else	/* IRE_ILL_CN */
-	if (fdp && fdp->fd_ifname[0] != 0)
-		ifname = fdp->fd_ifname;
-
-	DB_CKSUMFLAGS(mb) = 0;	/* disable hardware checksum */
-	mp = pfil_make_dl_packet(mb, ip, target, ifname, &q);
-	if (mp == NULL)
-	{
-		goto bad_fastroute;
-	}
-	mb = mp;
-#endif	/* IRE_ILL_CN */
-
-#ifdef IRE_ILL_CN
-	if (mp != NULL) {
-#else
-	if (dir != NULL) {
-#if SOLARIS2 < 8
-		mp = dir->ire_ll_hdr_mp;
-		hlen = dir->ire_ll_hdr_length;
-#elif (SOLARIS2 >= 8) && (SOLARIS2 <= 10)
-		mp = dir->ire_fp_mp;
-		hlen = mp ? mp->b_wptr - mp->b_rptr : 0;
-		if (mp == NULL)
-			mp = dir->ire_dlureq_mp;
-#else
-		mp = dir->ire_nce->nce_fp_mp;
-		hlen = mp ? mp->b_wptr - mp->b_rptr : 0;
-		if (mp == NULL)
-			mp = dir->ire_nce->nce_res_mp;
-#endif
-#endif
-		if (fin->fin_out == 0) {
-			void *saveqif;
-			u_32_t pass;
-
-			saveqif = fin->fin_ifp;
-			fin->fin_ifp = qif;
-			fin->fin_out = 1;
-			(void)fr_acctpkt(fin, &pass);
-			fin->fin_fr = NULL;
-			if (!fr || !(fr->fr_flags & FR_RETMASK))
-				(void) fr_checkstate(fin, &pass);
-
-			switch (fr_checknatout(fin, NULL))
-			{
-			/* FALLTHROUGH */
-			case 0 :
-			case 1 :
-				break;
-			case -1 :
-				goto bad_fastroute;
-			}
-
-			fin->fin_out = 0;
-			fin->fin_ifp = saveqif;
-		}
-#ifndef sparc
-		if (fin->fin_v == 4) {
-			__iplen = (u_short)ip->ip_len,
-			__ipoff = (u_short)ip->ip_off;
-
-			ip->ip_len = htons(__iplen);
-			ip->ip_off = htons(__ipoff);
-		}
-#endif
-#ifndef IRE_ILL_CN
-		ifp = qif->qf_ill;
-
-		if (mp != NULL) {
-			s = mb->b_rptr;
-			if (
-#if (SOLARIS2 >= 6) && defined(ICK_M_CTL_MAGIC)
-			    (dohwcksum &&
-			     ifp->ill_ick.ick_magic == ICK_M_CTL_MAGIC) ||
-#endif
-			    (hlen && (s - mb->b_datap->db_base) >= hlen)) {
-				s -= hlen;
-				mb->b_rptr = (u_char *)s;
-				bcopy((char *)mp->b_rptr, (char *)s, hlen);
-			} else {
-				mblk_t *mp2;
-
-				mp2 = copyb(mp);
-				if (mp2 == NULL)
-					goto bad_fastroute;
-				linkb(mp2, mb);
-				mb = mp2;
-			}
-		}
-		*mpp = mb;
-
-		if (dir->ire_stq != NULL)
-			q = dir->ire_stq;
-		else if (dir->ire_rfq != NULL)
-			q = WR(dir->ire_rfq);
-		if (q != NULL)
-			q = q->q_next;
-		if (q != NULL) {
-			RWLOCK_EXIT(&ipf_global);
-#if (SOLARIS2 >= 6) && defined(ICK_M_CTL_MAGIC)
-			if ((fin->fin_p == IPPROTO_TCP) && dohwcksum &&
-			    (ifp->ill_ick.ick_magic == ICK_M_CTL_MAGIC)) {
-				tcphdr_t *tcp;
-				u_32_t t;
-
-				tcp = (tcphdr_t *)((char *)ip + fin->fin_hlen);
-				t = ip->ip_src.s_addr;
-				t += ip->ip_dst.s_addr;
-				t += 30;
-				t = (t & 0xffff) + (t >> 16);
-				tcp->th_sum = t & 0xffff;
-			}
-#endif
-			putnext(q, mb);
-			ATOMIC_INCL(fr_frouteok[0]);
-#if SOLARIS2 >= 8
-			ire_refrele(dir);
-#endif
-			READ_ENTER(&ipf_global);
-			return 0;
-		}
-#else	/* IRE_ILL_CN */
-		mb->b_queue = q;
-		*mpp = mb;
-		pfil_send_dl_packet(q, mb);
-		ATOMIC_INCL(fr_frouteok[0]);
-		return 0;
-#endif	/* IRE_ILL_CN */
-	}
-bad_fastroute:
-#ifndef IRE_ILL_CN
-#if SOLARIS2 >= 8
-	if (dir != NULL)
-		ire_refrele(dir);
-#endif
-#endif
-	freemsg(mb);
-	ATOMIC_INCL(fr_frouteok[1]);
-	return -1;
-}
-
-
 /* ------------------------------------------------------------------------ */
 /* Function:    fr_pullup                                                   */
 /* Returns:     NULL == pullup failed, else pointer to protocol header      */
@@ -1571,7 +1426,7 @@
 {
 	qpktinfo_t *qpi = fin->fin_qpi;
 	int out = fin->fin_out, dpoff, ipoff;
-	mb_t *m = min;
+	mb_t *m = min, *m1, *m2;
 	char *ip;
 
 	if (m == NULL)
@@ -1605,6 +1460,22 @@
 					inc = 0;
 			}
 		}
+
+		/*
+		 * XXX This is here as a work around for a bug with DEBUG
+		 * XXX Solaris kernels.  The problem is b_prev is used by IP
+		 * XXX code as a way to stash the phyint_index for a packet,
+		 * XXX this doesn't get reset by IP but freeb does an ASSERT()
+		 * XXX for both of these to be NULL.  See 6442390.
+		 */
+		m1 = m;
+		m2 = m->b_prev;
+
+		do {
+			m1->b_next = NULL;
+			m1->b_prev = NULL;
+			m1 = m1->b_cont;
+		} while (m1);
 		if (pullupmsg(m, len + ipoff + inc) == 0) {
 			ATOMIC_INCL(frstats[out].fr_pull[1]);
 			FREE_MB_T(*fin->fin_mp);
@@ -1615,6 +1486,7 @@
 			qpi->qpi_data = NULL;
 			return NULL;
 		}
+		m->b_prev = m2;
 		m->b_rptr += inc;
 		fin->fin_m = m;
 		ip = MTOD(m, char *) + ipoff;
@@ -1630,3 +1502,410 @@
 		fin->fin_flx |= FI_COALESCE;
 	return ip;
 }
+
+
+/*
+ * Function:	fr_verifysrc
+ * Returns:	int (really boolean)
+ * Parameters:	fin - packet information
+ *
+ * Check whether the packet has a valid source address for the interface on
+ * which the packet arrived, implementing the "fr_chksrc" feature.
+ * Returns true iff the packet's source address is valid.
+ */
+int fr_verifysrc(fin)
+fr_info_t *fin;
+{
+	net_data_t net_data_p;
+	phy_if_t phy_ifdata_routeto;
+	struct sockaddr	sin;
+
+	if (fin->fin_v == 4) { 
+		net_data_p = ipf_ipv4;
+	} else if (fin->fin_v == 6) { 
+		net_data_p = ipf_ipv6;
+	} else { 
+		return (0); 
+	}
+
+	/* Get the index corresponding to the if name */
+	sin.sa_family = (fin->fin_v == 4) ? AF_INET : AF_INET6;
+	bcopy(&fin->fin_saddr, &sin.sa_data, sizeof (struct in_addr));
+	phy_ifdata_routeto = net_routeto(net_data_p, &sin);
+
+	return (((phy_if_t)fin->fin_ifp == phy_ifdata_routeto) ? 1 : 0); 
+}
+
+
+/*
+ * Function:	fr_fastroute
+ * Returns:	 0: success;
+ *		-1: failed
+ * Parameters:
+ *	mb: the message block where ip head starts
+ *	mpp: the pointer to the pointer of the orignal
+ *		packet message
+ *	fin: packet information
+ *	fdp: destination interface information
+ *	if it is NULL, no interface information provided.
+ *
+ * This function is for fastroute/to/dup-to rules. It calls
+ * pfil_make_lay2_packet to search route, make lay-2 header
+ * ,and identify output queue for the IP packet.
+ * The destination address depends on the following conditions:
+ * 1: for fastroute rule, fdp is passed in as NULL, so the
+ *	destination address is the IP Packet's destination address
+ * 2: for to/dup-to rule, if an ip address is specified after
+ *	the interface name, this address is the as destination
+ *	address. Otherwise IP Packet's destination address is used
+ */
+int fr_fastroute(mb, mpp, fin, fdp)
+mblk_t *mb, **mpp;
+fr_info_t *fin;
+frdest_t *fdp;
+{
+        net_data_t net_data_p;
+	net_inject_t inj_data;
+	mblk_t *mp = NULL;
+	frentry_t *fr = fin->fin_fr;
+	qpktinfo_t *qpi;
+	ip_t *ip;
+
+	struct sockaddr_in *sin;
+	struct sockaddr_in6 *sin6;
+	struct sockaddr *sinp;
+#ifndef	sparc
+	u_short __iplen, __ipoff;
+#endif
+
+	if (fin->fin_v == 4) {
+		net_data_p = ipf_ipv4;
+	} else if (fin->fin_v == 6) {
+		net_data_p = ipf_ipv6;
+	} else {
+		return (-1);
+	}
+
+	ip = fin->fin_ip;
+	qpi = fin->fin_qpi;
+
+	/*
+	 * If this is a duplicate mblk then we want ip to point at that
+	 * data, not the original, if and only if it is already pointing at
+	 * the current mblk data.
+	 *
+	 * Otherwise, if it's not a duplicate, and we're not already pointing
+	 * at the current mblk data, then we want to ensure that the data
+	 * points at ip.
+	 */
+
+	if ((ip == (ip_t *)qpi->qpi_m->b_rptr) && (qpi->qpi_m != mb)) {
+		ip = (ip_t *)mb->b_rptr;
+	} else if ((qpi->qpi_m == mb) && (ip != (ip_t *)qpi->qpi_m->b_rptr)) {
+		qpi->qpi_m->b_rptr = (uchar_t *)ip;
+		qpi->qpi_off = 0;
+	}
+
+	/*
+	 * If there is another M_PROTO, we don't want it
+	 */
+	if (*mpp != mb) {
+		mp = unlinkb(*mpp);
+		freeb(*mpp);
+		*mpp = mp;
+	}
+
+	sinp = (struct sockaddr *)&inj_data.ni_addr;
+	sin = (struct sockaddr_in *)sinp;
+	sin6 = (struct sockaddr_in6 *)sinp;
+	bzero((char *)&inj_data.ni_addr, sizeof (inj_data.ni_addr));
+	inj_data.ni_addr.ss_family = (fin->fin_v == 4) ? AF_INET : AF_INET6;
+	inj_data.ni_packet = mb;
+
+	/*
+	 * In case we're here due to "to <if>" being used with
+	 * "keep state", check that we're going in the correct
+	 * direction.
+	 */
+	if (fdp != NULL) {
+		if ((fr != NULL) && (fdp->fd_ifp != NULL) &&
+			(fin->fin_rev != 0) && (fdp == &fr->fr_tif))
+			goto bad_fastroute;
+		inj_data.ni_physical = (phy_if_t)fdp->fd_ifp;
+		if (fin->fin_v == 4) {
+			sin->sin_addr = fdp->fd_ip;
+		} else {
+			sin6->sin6_addr = fdp->fd_ip6.in6;
+		}
+	} else {
+		if (fin->fin_v == 4) {
+			sin->sin_addr = ip->ip_dst;
+		} else {
+			sin6->sin6_addr = ((ip6_t *)ip)->ip6_dst;
+		}
+		inj_data.ni_physical = net_routeto(net_data_p, sinp);
+	}
+
+	/* disable hardware checksum */
+	DB_CKSUMFLAGS(mb) = 0;
+
+	*mpp = mb;
+
+	if (fin->fin_out == 0) {
+		void *saveifp;
+		u_32_t pass;
+
+		saveifp = fin->fin_ifp;
+		fin->fin_ifp = (void *)inj_data.ni_physical;
+		fin->fin_out = 1;
+		(void) fr_acctpkt(fin, &pass);
+		fin->fin_fr = NULL;
+		if (!fr || !(fr->fr_flags & FR_RETMASK))
+			(void) fr_checkstate(fin, &pass);
+		switch (fr_checknatout(fin, NULL))
+		{
+		/* FALLTHROUGH */
+		case 0 :
+		case 1 :
+			break;
+		case -1 :
+			goto bad_fastroute;
+		}
+		fin->fin_out = 0;
+		fin->fin_ifp = saveifp;
+
+		if (fin->fin_nat != NULL)
+			fr_natderef((nat_t **)&fin->fin_nat);
+	}
+#ifndef	sparc
+	if (fin->fin_v == 4) {
+		__iplen = (u_short)ip->ip_len,
+		__ipoff = (u_short)ip->ip_off;
+
+		ip->ip_len = htons(__iplen);
+		ip->ip_off = htons(__ipoff);
+	}
+#endif
+
+	if (net_data_p) {
+		if (net_inject(net_data_p, NI_DIRECT_OUT, &inj_data) < 0) {
+			return (-1);
+		}
+	}
+
+	fr_frouteok[0]++;
+	return 0;
+bad_fastroute:
+	freemsg(mb);
+	fr_frouteok[1]++;
+	return -1;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    ipf_hook_out                                                */
+/* Returns:     int - 0 == packet ok, else problem, free packet if not done */
+/* Parameters:  event(I)     - pointer to event                             */
+/*              info(I)      - pointer to hook information for firewalling  */
+/*                                                                          */
+/* Calling ipf_hook.                                                        */
+/* ------------------------------------------------------------------------ */
+/*ARGSUSED*/
+int ipf_hook_out(hook_event_token_t token, hook_data_t info)
+{
+	return ipf_hook(info, 1, 0);
+}
+
+/* ------------------------------------------------------------------------ */
+/* Function:    ipf_hook_in                                                 */
+/* Returns:     int - 0 == packet ok, else problem, free packet if not done */
+/* Parameters:  event(I)     - pointer to event                             */
+/*              info(I)      - pointer to hook information for firewalling  */
+/*                                                                          */
+/* Calling ipf_hook.                                                        */
+/* ------------------------------------------------------------------------ */
+/*ARGSUSED*/
+int ipf_hook_in(hook_event_token_t token, hook_data_t info)
+{
+	return ipf_hook(info, 0, 0);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    ipf_hook_loop_out                                           */
+/* Returns:     int - 0 == packet ok, else problem, free packet if not done */
+/* Parameters:  event(I)     - pointer to event                             */
+/*              info(I)      - pointer to hook information for firewalling  */
+/*                                                                          */
+/* Calling ipf_hook.                                                        */
+/* ------------------------------------------------------------------------ */
+/*ARGSUSED*/
+int ipf_hook_loop_out(hook_event_token_t token, hook_data_t info)
+{
+	return ipf_hook(info, 1, 1);
+}
+
+/* ------------------------------------------------------------------------ */
+/* Function:    ipf_hook_loop_in                                            */
+/* Returns:     int - 0 == packet ok, else problem, free packet if not done */
+/* Parameters:  event(I)     - pointer to event                             */
+/*              info(I)      - pointer to hook information for firewalling  */
+/*                                                                          */
+/* Calling ipf_hook.                                                        */
+/* ------------------------------------------------------------------------ */
+/*ARGSUSED*/
+int ipf_hook_loop_in(hook_event_token_t token, hook_data_t info)
+{
+	return ipf_hook(info, 0, 1);
+}
+
+/* ------------------------------------------------------------------------ */
+/* Function:    ipf_hook                                                    */
+/* Returns:     int - 0 == packet ok, else problem, free packet if not done */
+/* Parameters:  info(I)      - pointer to hook information for firewalling  */
+/*              out(I)       - whether packet is going in or out            */
+/*              loopback(I)  - whether packet is a loopback packet or not   */
+/*                                                                          */
+/* Stepping stone function between the IP mainline and IPFilter.  Extracts  */
+/* parameters out of the info structure and forms them up to be useful for  */
+/* calling ipfilter.                                                        */
+/* ------------------------------------------------------------------------ */
+int ipf_hook(hook_data_t info, int out, int loopback)
+{
+	hook_pkt_event_t *fw;
+	int rval, v, hlen;
+	qpktinfo_t qpi;
+	u_short swap;
+	phy_if_t phy; 
+	ip_t *ip;
+
+	fw = (hook_pkt_event_t *)info;
+
+	ASSERT(fw != NULL);
+	phy = (out == 0) ? fw->hpe_ifp : fw->hpe_ofp;
+
+	ip = fw->hpe_hdr;
+	v = ip->ip_v;
+	if (v == IPV4_VERSION) {
+		swap = ntohs(ip->ip_len);
+		ip->ip_len = swap;
+		swap = ntohs(ip->ip_off);
+		ip->ip_off = swap;
+
+		hlen = IPH_HDR_LENGTH(ip);
+	} else
+		hlen = sizeof (ip6_t);
+
+	bzero(&qpi, sizeof (qpktinfo_t));
+
+	qpi.qpi_m = fw->hpe_mb;
+	qpi.qpi_data = fw->hpe_hdr;
+	qpi.qpi_off = (char *)qpi.qpi_data - (char *)fw->hpe_mb->b_rptr;
+	qpi.qpi_ill = (void *)phy;
+	if (loopback)
+		qpi.qpi_flags = QPI_NOCKSUM;
+	else
+		qpi.qpi_flags = 0;
+
+	rval = fr_check(fw->hpe_hdr, hlen, qpi.qpi_ill, out, &qpi, fw->hpe_mp);
+
+	/* For fastroute cases, fr_check returns 0 with mp set to NULL */
+	if (rval == 0 && *(fw->hpe_mp) == NULL)
+		rval = 1;
+
+	/* Notify IP the packet mblk_t and IP header pointers. */	
+	fw->hpe_mb = qpi.qpi_m;
+	fw->hpe_hdr = qpi.qpi_data;
+	if ((rval == 0) && (v == IPV4_VERSION)) {
+		ip = qpi.qpi_data;
+		swap = ntohs(ip->ip_len);
+		ip->ip_len = swap;
+		swap = ntohs(ip->ip_off);
+		ip->ip_off = swap;
+	}
+	return rval;
+
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    ipf_nic_event_v4                                            */
+/* Returns:     int - 0 == no problems encountered                          */
+/* Parameters:  event(I)     - pointer to event                             */
+/*              info(I)      - pointer to information about a NIC event     */
+/*                                                                          */
+/* Function to receive asynchronous NIC events from IP                      */
+/* ------------------------------------------------------------------------ */
+/*ARGSUSED*/
+int ipf_nic_event_v4(hook_event_token_t event, hook_data_t info)
+{
+	struct sockaddr_in *sin;
+	hook_nic_event_t *hn;
+
+	hn = (hook_nic_event_t *)info;
+
+	switch (hn->hne_event)
+	{
+	case NE_PLUMB :
+		frsync(IPFSYNC_NEWIFP, 4, (void *)hn->hne_nic, hn->hne_data);
+		fr_natifpsync(IPFSYNC_NEWIFP, (void *)hn->hne_nic,
+			      hn->hne_data);
+		fr_statesync(IPFSYNC_NEWIFP, 4, (void *)hn->hne_nic,
+			     hn->hne_data);
+		break;
+
+	case NE_UNPLUMB :
+		frsync(IPFSYNC_OLDIFP, 4, (void *)hn->hne_nic, NULL);
+		fr_natifpsync(IPFSYNC_OLDIFP, (void *)hn->hne_nic, NULL);
+		fr_statesync(IPFSYNC_OLDIFP, 4, (void *)hn->hne_nic, NULL);
+		break;
+
+	case NE_ADDRESS_CHANGE :
+		sin = hn->hne_data;
+		fr_nataddrsync((void *)hn->hne_nic, &sin->sin_addr);
+		break;
+
+	default :
+		break;
+	}
+
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    ipf_nic_event_v6                                            */
+/* Returns:     int - 0 == no problems encountered                          */
+/* Parameters:  event(I)     - pointer to event                             */
+/*              info(I)      - pointer to information about a NIC event     */
+/*                                                                          */
+/* Function to receive asynchronous NIC events from IP                      */
+/* ------------------------------------------------------------------------ */
+/*ARGSUSED*/
+int ipf_nic_event_v6(hook_event_token_t event, hook_data_t info)
+{
+	hook_nic_event_t *hn;
+
+	hn = (hook_nic_event_t *)info;
+
+	switch (hn->hne_event)
+	{
+	case NE_PLUMB :
+		frsync(IPFSYNC_NEWIFP, 6, (void *)hn->hne_nic, hn->hne_data);
+		fr_statesync(IPFSYNC_NEWIFP, 6, (void *)hn->hne_nic,
+			     hn->hne_data);
+		break;
+
+	case NE_UNPLUMB :
+		frsync(IPFSYNC_OLDIFP, 6, (void *)hn->hne_nic, NULL);
+		fr_statesync(IPFSYNC_OLDIFP, 6, (void *)hn->hne_nic, NULL);
+		break;
+
+	case NE_ADDRESS_CHANGE :
+		break;
+	default :
+		break;
+	}
+
+	return 0;
+}
--- a/usr/src/uts/common/inet/ipf/ip_log.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ipf/ip_log.c	Fri Oct 20 16:37:58 2006 -0700
@@ -254,15 +254,16 @@
 	ipflog_t ipfl;
 	u_char p;
 	mb_t *m;
-# if (SOLARIS || defined(__hpux)) && defined(_KERNEL)
-#  ifndef IRE_ILL_CN
+# if SOLARIS && defined(_KERNEL)
+	net_data_t nif;
+	void *ifp;
+# else
+#  if defined(__hpux) && defined(_KERNEL)
 	qif_t *ifp;
 #  else
-	s_ill_t *ifp;
-#  endif /* IRE_ILL_CN */
-# else
 	struct ifnet *ifp;
-# endif /* SOLARIS || __hpux */
+#  endif
+# endif /* SOLARIS */
 
 	ipfl.fl_nattag.ipt_num[0] = 0;
 	m = fin->fin_m;
@@ -328,27 +329,42 @@
 	 * Get the interface number and name to which this packet is
 	 * currently associated.
 	 */
-# if (SOLARIS || defined(__hpux)) && defined(_KERNEL)
+# if SOLARIS && defined(_KERNEL)
+	ipfl.fl_unit = (u_int)0;
+	nif = NULL;
+	if (fin->fin_fi.fi_v == 4)
+		nif = ipf_ipv4;
+	else if (fin->fin_fi.fi_v == 6)
+		nif = ipf_ipv6;
+	if (nif != NULL) {
+		if (net_getifname(nif, (phy_if_t)ifp,
+		    ipfl.fl_ifname, sizeof(ipfl.fl_ifname)) != 0)
+			return (-1);
+	}
+
+# else
+#  if defined(__hpux) && defined(_KERNEL)
 	ipfl.fl_unit = (u_int)0;
 	(void) strncpy(ipfl.fl_ifname, IFNAME(ifp), sizeof(ipfl.fl_ifname));
-# else
-#  if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \
-      (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
-      (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
+#  else
+#   if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \
+       (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
+       (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
 	COPYIFNAME(ifp, ipfl.fl_ifname);
-#  else
+#   else
 	ipfl.fl_unit = (u_int)ifp->if_unit;
-#   if defined(_KERNEL)
+#    if defined(_KERNEL)
 	if ((ipfl.fl_ifname[0] = ifp->if_name[0]))
 		if ((ipfl.fl_ifname[1] = ifp->if_name[1]))
 			if ((ipfl.fl_ifname[2] = ifp->if_name[2]))
 				ipfl.fl_ifname[3] = ifp->if_name[3];
-#   else
+#    else
 	(void) strncpy(ipfl.fl_ifname, IFNAME(ifp), sizeof(ipfl.fl_ifname));
 	ipfl.fl_ifname[sizeof(ipfl.fl_ifname) - 1] = '\0';
+#    endif
 #   endif
-#  endif
-# endif /* __hpux || SOLARIS */
+#  endif /* __hpux */
+# endif /* SOLARIS */
 	mlen = fin->fin_plen - hlen;
 	if (!ipl_logall) {
 		mlen = (flags & FR_LOGBODY) ? MIN(mlen, 128) : 0;
@@ -617,26 +633,30 @@
 		 */
 		iplt[unit] = ipl->ipl_next;
 		iplused[unit] -= dlen;
+		if (iplt[unit] == NULL) {
+			iplh[unit] = &iplt[unit];
+			ipll[unit] = NULL;
+		}
 		MUTEX_EXIT(&ipl_mutex);
 		SPL_X(s);
 		error = UIOMOVE((caddr_t)ipl, dlen, UIO_READ, uio);
 		if (error) {
 			SPL_NET(s);
 			MUTEX_ENTER(&ipl_mutex);
+			iplused[unit] += dlen;
 			ipl->ipl_next = iplt[unit];
 			iplt[unit] = ipl;
-			iplused[unit] += dlen;
+			ipll[unit] = ipl;
+			if (iplh[unit] == &iplt[unit]) {
+				*iplh[unit] = ipl;
+				iplh[unit] = &ipl->ipl_next;
+			}
 			break;
 		}
 		MUTEX_ENTER(&ipl_mutex);
 		KFREES((caddr_t)ipl, dlen);
 		SPL_NET(s);
 	}
-	if (!iplt[unit]) {
-		iplused[unit] = 0;
-		iplh[unit] = &iplt[unit];
-		ipll[unit] = NULL;
-	}
 
 	MUTEX_EXIT(&ipl_mutex);
 	SPL_X(s);
--- a/usr/src/uts/common/inet/ipf/ip_nat.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ipf/ip_nat.c	Fri Oct 20 16:37:58 2006 -0700
@@ -171,9 +171,6 @@
 natstat_t nat_stats;
 int	fr_nat_lock = 0;
 int	fr_nat_init = 0;
-#if SOLARIS
-extern	int		pfil_delayed_copy;
-#endif
 
 static	int	nat_flushtable __P((void));
 static	int	nat_clearlist __P((void));
@@ -199,7 +196,7 @@
 				      tcphdr_t *, nat_t **, int));
 static	void	nat_resolverule __P((ipnat_t *));
 static	nat_t	*fr_natclone __P((fr_info_t *, nat_t *));
-static	void	nat_mssclamp __P((tcphdr_t *, u_32_t, fr_info_t *, u_short *));
+static	void	nat_mssclamp __P((tcphdr_t *, u_32_t, u_short *));
 static	INLINE	int nat_wildok __P((nat_t *, int, int, int, int));
 
 
@@ -497,14 +494,12 @@
 /* ------------------------------------------------------------------------ */
 /* Function:    fix_outcksum                                                */
 /* Returns:     Nil                                                         */
-/* Parameters:  fin(I) - pointer to packet information                      */
-/*              sp(I)  - location of 16bit checksum to update               */
+/* Parameters:  sp(I)  - location of 16bit checksum to update               */
 /*              n((I)  - amount to adjust checksum by                       */
 /*                                                                          */
 /* Adjusts the 16bit checksum by "n" for packets going out.                 */
 /* ------------------------------------------------------------------------ */
-void fix_outcksum(fin, sp, n)
-fr_info_t *fin;
+void fix_outcksum(sp, n)
 u_short *sp;
 u_32_t n;
 {
@@ -514,13 +509,6 @@
 	if (n == 0)
 		return;
 
-	if (n & NAT_HW_CKSUM) {
-		n &= 0xffff;
-		n += fin->fin_dlen;
-		n = (n & 0xffff) + (n >> 16);
-		*sp = n & 0xffff;
-		return;
-	}
 	sum1 = (~ntohs(*sp)) & 0xffff;
 	sum1 += (n);
 	sum1 = (sum1 >> 16) + (sum1 & 0xffff);
@@ -534,14 +522,12 @@
 /* ------------------------------------------------------------------------ */
 /* Function:    fix_incksum                                                 */
 /* Returns:     Nil                                                         */
-/* Parameters:  fin(I) - pointer to packet information                      */
-/*              sp(I)  - location of 16bit checksum to update               */
+/* Parameters:  sp(I)  - location of 16bit checksum to update               */
 /*              n((I)  - amount to adjust checksum by                       */
 /*                                                                          */
 /* Adjusts the 16bit checksum by "n" for packets going in.                  */
 /* ------------------------------------------------------------------------ */
-void fix_incksum(fin, sp, n)
-fr_info_t *fin;
+void fix_incksum(sp, n)
 u_short *sp;
 u_32_t n;
 {
@@ -551,13 +537,6 @@
 	if (n == 0)
 		return;
 
-	if (n & NAT_HW_CKSUM) {
-		n &= 0xffff;
-		n += fin->fin_dlen;
-		n = (n & 0xffff) + (n >> 16);
-		*sp = n & 0xffff;
-		return;
-	}
 	sum1 = (~ntohs(*sp)) & 0xffff;
 	sum1 += ~(n) & 0xffff;
 	sum1 = (sum1 >> 16) + (sum1 & 0xffff);
@@ -980,9 +959,6 @@
 	}
 	n = NULL;
 	nat_stats.ns_rules++;
-#if SOLARIS
-	pfil_delayed_copy = 0;
-#endif
 	if (getlock) {
 		RWLOCK_EXIT(&ipf_nat);			/* WRITE */
 	}
@@ -1067,10 +1043,6 @@
 			appr_free(n->in_apr);
 		KFREE(n);
 		nat_stats.ns_rules--;
-#if SOLARIS
-		if (nat_stats.ns_rules == 0)
-			pfil_delayed_copy = 1;
-#endif
 	} else {
 		n->in_flags |= IPN_DELETE;
 		n->in_next = NULL;
@@ -1602,10 +1574,6 @@
 				appr_free(ipn->in_apr);
 			KFREE(ipn);
 			nat_stats.ns_rules--;
-#if SOLARIS
-			if (nat_stats.ns_rules == 0)
-				pfil_delayed_copy = 1;
-#endif
 		}
 	}
 
@@ -1695,9 +1663,6 @@
 		}
 		i++;
 	}
-#if SOLARIS
-	pfil_delayed_copy = 1;
-#endif
 	nat_masks = 0;
 	rdr_masks = 0;
 	return i;
@@ -2147,9 +2112,6 @@
 	natinfo_t ni;
 	u_32_t sumd;
 	int move;
-#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_M_CTL_MAGIC)
-	qpktinfo_t *qpi = fin->fin_qpi;
-#endif
 
 	if (nat_stats.ns_inuse >= ipf_nattable_max) {
 		nat_stats.ns_memfail++;
@@ -2272,23 +2234,24 @@
 		dport = 0;
 	}
 
+	/*
+	 * nat_sumd[0] stores adjustment value including both IP address and
+	 * port number changes. nat_sumd[1] stores adjustment value only for
+	 * IP address changes, to be used for pseudo header adjustment, in
+	 * case hardware partial checksum offload is offered.
+	 */
 	CALC_SUMD(ni.nai_sum1, ni.nai_sum2, sumd);
 	nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16);
-#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_M_CTL_MAGIC)
-	if ((flags & IPN_TCP) && dohwcksum &&
-#ifndef IRE_ILL_CN
-	    (((ill_t *)qpi->qpi_ill)->ill_ick.ick_magic == ICK_M_CTL_MAGIC)) {
-#else
-	    (((s_ill_t *)qpi->qpi_ill)->ill_ick.ick_magic == ICK_M_CTL_MAGIC)) {
-#endif /* IRE_ILL_CN */
+#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
+	if (flags & IPN_TCPUDP) {
+		ni.nai_sum1 = LONG_SUM(in.s_addr);
 		if (direction == NAT_OUTBOUND)
-			ni.nai_sum1 = LONG_SUM(in.s_addr);
+			ni.nai_sum2 = LONG_SUM(ntohl(fin->fin_saddr));
 		else
-			ni.nai_sum1 = LONG_SUM(ntohl(fin->fin_saddr));
-		ni.nai_sum1 += LONG_SUM(ntohl(fin->fin_daddr));
-		ni.nai_sum1 += 30;
-		ni.nai_sum1 = (ni.nai_sum1 & 0xffff) + (ni.nai_sum1 >> 16);
-		nat->nat_sumd[1] = NAT_HW_CKSUM|(ni.nai_sum1 & 0xffff);
+			ni.nai_sum2 = LONG_SUM(ntohl(fin->fin_daddr));
+
+		CALC_SUMD(ni.nai_sum1, ni.nai_sum2, sumd);
+		nat->nat_sumd[1] = (sumd & 0xffff) + (sumd >> 16);
 	} else
 #endif
 		nat->nat_sumd[1] = nat->nat_sumd[0];
@@ -2357,12 +2320,8 @@
 
 	np = ni->nai_np;
 
-	if (np->in_ifps[0] != NULL) {
-		(void) COPYIFNAME(np->in_ifps[0], nat->nat_ifnames[0]);
-	}
-	if (np->in_ifps[1] != NULL) {
-		(void) COPYIFNAME(np->in_ifps[1], nat->nat_ifnames[1]);
-	}
+	COPYIFNAME(fin->fin_ifp, nat->nat_ifnames[0], fin->fin_v);
+
 #ifdef	IPFILTER_SYNC
 	if ((nat->nat_flags & SI_CLONE) == 0)
 		nat->nat_sync = ipfsync_new(SMC_NAT, fin, nat);
@@ -2880,7 +2839,7 @@
 	if (sumd2 != 0) {
 		sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16);
 		sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16);
-		fix_incksum(fin, &icmp->icmp_cksum, sumd2);
+		fix_incksum(&icmp->icmp_cksum, sumd2);
 	}
 	return nat;
 }
@@ -3674,10 +3633,19 @@
 {
 	icmphdr_t *icmp;
 	u_short *csump;
+	u_32_t sumd;
 	tcphdr_t *tcp;
 	ipnat_t *np;
 	int i;
 
+#if SOLARIS && defined(_KERNEL)
+	net_data_t net_data_p;
+	if (fin->fin_v == 4)
+		net_data_p = ipf_ipv4;
+	else
+		net_data_p = ipf_ipv6;
+#endif
+
 	tcp = NULL;
 	icmp = NULL;
 	csump = NULL;
@@ -3690,7 +3658,7 @@
 	nat->nat_bytes[1] += fin->fin_plen;
 	nat->nat_pkts[1]++;
 	MUTEX_EXIT(&nat->nat_lock);
-
+	
 	/*
 	 * Fix up checksums, not by recalculating them, but
 	 * simply computing adjustments.
@@ -3699,14 +3667,16 @@
 	 * IPFilter is called before the checksum needs calculating so there
 	 * is no call to modify whatever is in the header now.
 	 */
-	if (fin->fin_v == 4) {
+	ASSERT(fin->fin_m != NULL);
+	if (fin->fin_v == 4 && !NET_IS_HCK_L3_FULL(net_data_p, fin->fin_m)) {
 		if (nflags == IPN_ICMPERR) {
-			u_32_t s1, s2, sumd;
+			u_32_t s1, s2;
 
 			s1 = LONG_SUM(ntohl(fin->fin_saddr));
 			s2 = LONG_SUM(ntohl(nat->nat_outip.s_addr));
 			CALC_SUMD(s1, s2, sumd);
-			fix_outcksum(fin, &fin->fin_ip->ip_sum, sumd);
+
+			fix_outcksum(&fin->fin_ip->ip_sum, sumd);
 		}
 #if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \
     defined(linux) || defined(BRIDGE_IPF)
@@ -3718,11 +3688,11 @@
 			 * to do NAT as a bridge, that code doesn't exist.
 			 */
 			if (nat->nat_dir == NAT_OUTBOUND)
-				fix_outcksum(fin, &fin->fin_ip->ip_sum,
-					     nat->nat_ipsumd);
+				fix_outcksum(&fin->fin_ip->ip_sum,
+					    nat->nat_ipsumd);
 			else
-				fix_incksum(fin, &fin->fin_ip->ip_sum,
-					    nat->nat_ipsumd);
+				fix_incksum(&fin->fin_ip->ip_sum,
+				 	   nat->nat_ipsumd);
 		}
 #endif
 	}
@@ -3750,11 +3720,17 @@
 	/*
 	 * The above comments do not hold for layer 4 (or higher) checksums...
 	 */
-	if (csump != NULL) {
+	if (csump != NULL && !NET_IS_HCK_L4_FULL(net_data_p, fin->fin_m)) {
+		if (nflags & IPN_TCPUDP &&
+	   	    NET_IS_HCK_L4_PART(net_data_p, fin->fin_m))
+			sumd = nat->nat_sumd[1];
+		else
+			sumd = nat->nat_sumd[0];
+
 		if (nat->nat_dir == NAT_OUTBOUND)
-			fix_outcksum(fin, csump, nat->nat_sumd[1]);
+			fix_outcksum(csump, sumd);
 		else
-			fix_incksum(fin, csump, nat->nat_sumd[1]);
+			fix_incksum(csump, sumd);
 	}
 #ifdef	IPFILTER_SYNC
 	ipfsync_update(SMC_NAT, fin, nat->nat_sync);
@@ -3968,11 +3944,20 @@
 u_32_t nflags;
 {
 	icmphdr_t *icmp;
-	u_short *csump;
+	u_short *csump, *csump1;
+	u_32_t sumd;
 	tcphdr_t *tcp;
 	ipnat_t *np;
 	int i;
 
+#if SOLARIS && defined(_KERNEL)
+	net_data_t net_data_p;
+	if (fin->fin_v == 4)
+		net_data_p = ipf_ipv4;
+	else
+		net_data_p = ipf_ipv6;
+#endif
+
 	tcp = NULL;
 	csump = NULL;
 	np = nat->nat_ptr;
@@ -4027,9 +4012,9 @@
 #if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \
      defined(__osf__) || defined(linux)
 	if (nat->nat_dir == NAT_OUTBOUND)
-		fix_incksum(fin, &fin->fin_ip->ip_sum, nat->nat_ipsumd);
+		fix_incksum(&fin->fin_ip->ip_sum, nat->nat_ipsumd);
 	else
-		fix_outcksum(fin, &fin->fin_ip->ip_sum, nat->nat_ipsumd);
+		fix_outcksum(&fin->fin_ip->ip_sum, nat->nat_ipsumd);
 #endif
 
 	if (!(fin->fin_flx & FI_SHORT) && (fin->fin_off == 0)) {
@@ -4050,14 +4035,30 @@
 
 	nat_update(fin, nat, np);
 
+#if SOLARIS && defined(_KERNEL)
+	if (nflags & IPN_TCPUDP &&
+	    NET_IS_HCK_L4_PART(net_data_p, fin->fin_m)) {
+		sumd = nat->nat_sumd[1];
+		csump1 = &(fin->fin_m->b_datap->db_struioun.cksum.cksum_val.u16);
+		if (csump1 != NULL) {
+			if (nat->nat_dir == NAT_OUTBOUND)
+				fix_incksum(csump1, sumd);
+			else
+				fix_outcksum(csump1, sumd);
+		}
+	} else
+#endif
+		sumd = nat->nat_sumd[0];
+
 	/*
-	 * The above comments do not hold for layer 4 (or higher) checksums...
+	 * Inbound packets always need to have their address adjusted in case	
+	 * code following this validates it.
 	 */
 	if (csump != NULL) {
 		if (nat->nat_dir == NAT_OUTBOUND)
-			fix_incksum(fin, csump, nat->nat_sumd[0]);
+			fix_incksum(csump, sumd);
 		else
-			fix_outcksum(fin, csump, nat->nat_sumd[0]);
+			fix_outcksum(csump, sumd);
 	}
 	ATOMIC_INCL(nat_stats.ns_mapped[0]);
 	fin->fin_flx |= FI_NATED;
@@ -4110,7 +4111,7 @@
 		 * only deal IPv4 for now.
 		 */
 		if ((nat->nat_mssclamp != 0) && (tcp->th_flags & TH_SYN) != 0)
-			nat_mssclamp(tcp, nat->nat_mssclamp, fin, csump);
+			nat_mssclamp(tcp, nat->nat_mssclamp, csump);
 
 		break;
 
@@ -4265,32 +4266,28 @@
 
 
 /* ------------------------------------------------------------------------ */
-/* Function:    fr_natsync                                                  */
+/* Function:    fr_nataddrsync                                              */
 /* Returns:     Nil                                                         */
-/* Parameters:  ifp(I) - pointer to network interface                       */
+/* Parameters:  ifp(I) -  pointer to network interface                      */
+/*              addr(I) - pointer to new network address                    */
 /*                                                                          */
 /* Walk through all of the currently active NAT sessions, looking for those */
-/* which need to have their translated address updated.                     */
+/* which need to have their translated address updated (where the interface */
+/* matches the one passed in) and change it, recalculating the checksum sum */
+/* difference too.                                                          */
 /* ------------------------------------------------------------------------ */
-void fr_natsync(ifp)
+void fr_nataddrsync(ifp, addr)
 void *ifp;
+struct in_addr *addr;
 {
 	u_32_t sum1, sum2, sumd;
-	struct in_addr in;
-	ipnat_t *n;
 	nat_t *nat;
-	void *ifp2;
+	ipnat_t *np;
 	SPL_INT(s);
 
 	if (fr_running <= 0)
 		return;
 
-	/*
-	 * Change IP addresses for NAT sessions for any protocol except TCP
-	 * since it will break the TCP connection anyway.  The only rules
-	 * which will get changed are those which are "map ... -> 0/32",
-	 * where the rule specifies the address is taken from the interface.
-	 */
 	SPL_NET(s);
 	WRITE_ENTER(&ipf_nat);
 
@@ -4299,23 +4296,19 @@
 		return;
 	}
 
+	/*
+	 * Change IP addresses for NAT sessions for any protocol except TCP
+	 * since it will break the TCP connection anyway.  The only rules
+	 * which will get changed are those which are "map ... -> 0/32",
+	 * where the rule specifies the address is taken from the interface.
+	 */
 	for (nat = nat_instances; nat; nat = nat->nat_next) {
-		if ((nat->nat_flags & IPN_TCP) != 0)
-			continue;
-		n = nat->nat_ptr;
-		if ((n == NULL) ||
-		    (n->in_outip != 0) || (n->in_outmsk != 0xffffffff))
-			continue;
-		if (((ifp == NULL) || (ifp == nat->nat_ifps[0]) ||
-		     (ifp == nat->nat_ifps[1]))) {
-			nat->nat_ifps[0] = GETIFP(nat->nat_ifnames[0], 4);
-			if (nat->nat_ifnames[1][0] != '\0') {
-				nat->nat_ifps[1] = GETIFP(nat->nat_ifnames[1],
-							  4);
-			} else
-				nat->nat_ifps[1] = nat->nat_ifps[0];
-			ifp2 = nat->nat_ifps[0];
-			if (ifp2 == NULL)
+		if (addr != NULL) {
+			if (((ifp != NULL) && ifp != (nat->nat_ifps[0])) ||
+			    ((nat->nat_flags & IPN_TCP) != 0))
+				continue;
+			if (((np = nat->nat_ptr) == NULL) ||
+			    (np->in_nip || (np->in_outmsk != 0xffffffff)))
 				continue;
 
 			/*
@@ -4323,31 +4316,145 @@
 			 * new one.
 			 */
 			sum1 = nat->nat_outip.s_addr;
-			if (fr_ifpaddr(4, FRI_NORMAL, ifp2, &in, NULL) != -1)
+			nat->nat_outip = *addr;
+			sum2 = nat->nat_outip.s_addr;
+
+		} else if (((ifp == NULL) || (ifp == nat->nat_ifps[0])) &&
+		    !(nat->nat_flags & IPN_TCP) && (np = nat->nat_ptr) &&
+		    (np->in_outmsk == 0xffffffff) && !np->in_nip) {
+			struct in_addr in;
+
+			/*
+			 * Change the map-to address to be the same as the
+			 * new one.
+			 */
+			sum1 = nat->nat_outip.s_addr;
+			if (fr_ifpaddr(4, FRI_NORMAL, nat->nat_ifps[0],
+				       &in, NULL) != -1)
 				nat->nat_outip = in;
 			sum2 = nat->nat_outip.s_addr;
-
-			if (sum1 == sum2)
-				continue;
-			/*
-			 * Readjust the checksum adjustment to take into
-			 * account the new IP#.
-			 */
-			CALC_SUMD(sum1, sum2, sumd);
-			/* XXX - dont change for TCP when solaris does
-			 * hardware checksumming.
-			 */
-			sumd += nat->nat_sumd[0];
-			nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16);
-			nat->nat_sumd[1] = nat->nat_sumd[0];
+		} else {
+			continue;
 		}
+
+		if (sum1 == sum2)
+			continue;
+		/*
+		 * Readjust the checksum adjustment to take into
+		 * account the new IP#.
+		 */
+		CALC_SUMD(sum1, sum2, sumd);
+		/* XXX - dont change for TCP when solaris does
+		 * hardware checksumming.
+		 */
+		sumd += nat->nat_sumd[0];
+		nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16);
+		nat->nat_sumd[1] = nat->nat_sumd[0];
 	}
 
-	for (n = nat_list; (n != NULL); n = n->in_next) {
-		if ((ifp == NULL) || (n->in_ifps[0] == ifp))
-			n->in_ifps[0] = fr_resolvenic(n->in_ifnames[0], 4);
-		if ((ifp == NULL) || (n->in_ifps[1] == ifp))
-			n->in_ifps[1] = fr_resolvenic(n->in_ifnames[1], 4);
+	RWLOCK_EXIT(&ipf_nat);
+	SPL_X(s);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function:    fr_natifpsync                                               */
+/* Returns:     Nil                                                         */
+/* Parameters:  action(I) - how we are syncing                              */
+/*              ifp(I)    - pointer to network interface                    */
+/*              name(I)   - name of interface to sync to                    */
+/*                                                                          */
+/* This function is used to resync the mapping of interface names and their */
+/* respective 'pointers'.  For "action == IPFSYNC_RESYNC", resync all       */
+/* interfaces by doing a new lookup of name to 'pointer'.  For "action ==   */
+/* IPFSYNC_NEWIFP", treat ifp as the new pointer value associated with      */
+/* "name" and for "action == IPFSYNC_OLDIFP", ifp is a pointer for which    */
+/* there is no longer any interface associated with it.                     */
+/* ------------------------------------------------------------------------ */
+void fr_natifpsync(action, ifp, name)
+int action;
+void *ifp;
+char *name;
+{
+#if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL)
+	int s;
+#endif
+	nat_t *nat;
+	ipnat_t *n;
+
+	if (fr_running <= 0)
+		return;
+
+	SPL_NET(s);
+	WRITE_ENTER(&ipf_nat);
+
+	if (fr_running <= 0) {
+		RWLOCK_EXIT(&ipf_nat);
+		return;
+	}
+
+	switch (action)
+	{
+	case IPFSYNC_RESYNC :
+		for (nat = nat_instances; nat; nat = nat->nat_next) {
+			if ((ifp == nat->nat_ifps[0]) ||
+			    (nat->nat_ifps[0] == (void *)-1)) {
+				nat->nat_ifps[0] =
+				    fr_resolvenic(nat->nat_ifnames[0], 4);
+			}
+
+			if ((ifp == nat->nat_ifps[1]) ||
+			    (nat->nat_ifps[1] == (void *)-1)) {
+				nat->nat_ifps[1] =
+				    fr_resolvenic(nat->nat_ifnames[1], 4);
+			}
+		}
+
+		for (n = nat_list; (n != NULL); n = n->in_next) {
+			if (n->in_ifps[0] == ifp ||
+			    n->in_ifps[0] == (void *)-1) {
+				n->in_ifps[0] =
+				    fr_resolvenic(n->in_ifnames[0], 4);
+			}
+			if (n->in_ifps[1] == ifp ||
+			    n->in_ifps[1] == (void *)-1) {
+				n->in_ifps[1] =
+				    fr_resolvenic(n->in_ifnames[1], 4);
+			}
+		}
+		break;
+	case IPFSYNC_NEWIFP :
+		for (nat = nat_instances; nat; nat = nat->nat_next) {
+			if (!strncmp(name, nat->nat_ifnames[0],
+				     sizeof(nat->nat_ifnames[0])))
+				nat->nat_ifps[0] = ifp;
+			if (!strncmp(name, nat->nat_ifnames[1],
+				     sizeof(nat->nat_ifnames[1])))
+				nat->nat_ifps[1] = ifp;
+		}
+		for (n = nat_list; (n != NULL); n = n->in_next) {
+			if (!strncmp(name, n->in_ifnames[0],
+				     sizeof(n->in_ifnames[0])))
+				n->in_ifps[0] = ifp;
+			if (!strncmp(name, n->in_ifnames[1],
+				     sizeof(n->in_ifnames[1])))
+				n->in_ifps[1] = ifp;
+		}
+		break;
+	case IPFSYNC_OLDIFP :
+		for (nat = nat_instances; nat; nat = nat->nat_next) {
+			if (ifp == nat->nat_ifps[0])
+				nat->nat_ifps[0] = (void *)-1;
+			if (ifp == nat->nat_ifps[1])
+				nat->nat_ifps[1] = (void *)-1;
+		}
+		for (n = nat_list; (n != NULL); n = n->in_next) {
+			if (n->in_ifps[0] == ifp)
+				n->in_ifps[0] = (void *)-1;
+			if (n->in_ifps[1] == ifp)
+				n->in_ifps[1] = (void *)-1;
+		}
+		break;
 	}
 	RWLOCK_EXIT(&ipf_nat);
 	SPL_X(s);
@@ -4638,17 +4745,15 @@
 /* Returns:     Nil                                                         */
 /* Parameters:  tcp(I)    - pointer to TCP header                           */
 /*              maxmss(I) - value to clamp the TCP MSS to                   */
-/*              fin(I)    - pointer to packet information                   */
 /*              csump(I)  - pointer to TCP checksum                         */
 /*                                                                          */
 /* Check for MSS option and clamp it if necessary.  If found and changed,   */
 /* then the TCP header checksum will be updated to reflect the change in    */
 /* the MSS.                                                                 */
 /* ------------------------------------------------------------------------ */
-static void nat_mssclamp(tcp, maxmss, fin, csump)
+static void nat_mssclamp(tcp, maxmss, csump)
 tcphdr_t *tcp;
 u_32_t maxmss;
-fr_info_t *fin;
 u_short *csump;
 {
 	u_char *cp, *ep, opt;
@@ -4684,7 +4789,7 @@
 					cp[2] = maxmss / 256;
 					cp[3] = maxmss & 0xff;
 					CALC_SUMD(mss, maxmss, sumd);
-					fix_outcksum(fin, csump, sumd);
+					fix_outcksum(csump, sumd);
 				}
 				break;
 			default:
--- a/usr/src/uts/common/inet/ipf/ip_proxy.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ipf/ip_proxy.c	Fri Oct 20 16:37:58 2006 -0700
@@ -462,10 +462,8 @@
 fr_info_t *fin;
 nat_t *nat;
 {
-#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
-# if defined(ICK_VALID)
+#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_VALID)
 	mb_t *m;
-# endif
 	int dosum = 1;
 #endif
 	tcphdr_t *tcp = NULL;
@@ -478,6 +476,13 @@
 #if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi)
 	u_32_t s1, s2, sd;
 #endif
+#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
+	net_data_t net_data_p;
+	if (fin->fin_v == 4)
+		net_data_p = ipf_ipv4;
+	else
+		net_data_p = ipf_ipv6;
+#endif
 
 	if (fin->fin_flx & FI_BAD) {
 		if (ipf_proxy_debug > 0)
@@ -564,15 +569,17 @@
 		 * If err != 0 then the data size of the packet has changed
 		 * so we need to recalculate the header checksums for the
 		 * packet.
+		 * inbound packets always need to be adjusted.
 		 */
 #if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi)
-		if (err != 0) {
+		if (err != 0 && (!fin->fin_out ||
+	    	    !NET_IS_HCK_L3_FULL(net_data_p, fin->fin_m))) {
 			short adjlen = err & 0xffff;
 
 			s1 = LONG_SUM(ip->ip_len - adjlen);
 			s2 = LONG_SUM(ip->ip_len);
 			CALC_SUMD(s1, s2, sd);
-			fix_outcksum(fin, &ip->ip_sum, sd);
+			fix_outcksum(&ip->ip_sum, sd);
 		}
 #endif
 
@@ -588,7 +595,9 @@
 		if (tcp != NULL) {
 			err = appr_fixseqack(fin, ip, aps, APR_INC(err));
 #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
-			if (dosum)
+			if (!fin->fin_out ||
+			    !NET_IS_HCK_L4_FULL(net_data_p, fin->fin_m) &&
+			    !NET_IS_HCK_L4_PART(net_data_p, fin->fin_m))
 				tcp->th_sum = fr_cksum(fin->fin_qfm, ip,
 						       IPPROTO_TCP, tcp);
 #else
@@ -597,7 +606,9 @@
 #endif
 		} else if ((udp != NULL) && (udp->uh_sum != 0)) {
 #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
-			if (dosum)
+			if (!fin->fin_out ||
+			    !NET_IS_HCK_L4_FULL(net_data_p, fin->fin_m) &&
+			    !NET_IS_HCK_L4_PART(net_data_p, fin->fin_m))
 				udp->uh_sum = fr_cksum(fin->fin_qfm, ip,
 						       IPPROTO_UDP, udp);
 #else
--- a/usr/src/uts/common/inet/ipf/ip_state.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ipf/ip_state.c	Fri Oct 20 16:37:58 2006 -0700
@@ -1092,15 +1092,15 @@
 
 		if (((ifp = fr->fr_ifas[1]) != NULL) &&
 		    (ifp != (void *)-1)) {
-			COPYIFNAME(ifp, is->is_ifname[(out << 1) + 1]);
+			COPYIFNAME(ifp, is->is_ifname[(out << 1) + 1], fr->fr_v);
 		}
 		if (((ifp = fr->fr_ifas[2]) != NULL) &&
 		    (ifp != (void *)-1)) {
-			COPYIFNAME(ifp, is->is_ifname[(1 - out) << 1]);
+			COPYIFNAME(ifp, is->is_ifname[(1 - out) << 1], fr->fr_v);
 		}
 		if (((ifp = fr->fr_ifas[3]) != NULL) &&
 		    (ifp != (void *)-1)) {
-			COPYIFNAME(ifp, is->is_ifname[((1 - out) << 1) + 1]);
+			COPYIFNAME(ifp, is->is_ifname[((1 - out) << 1) + 1], fr->fr_v);
 		}
 	} else {
 		pass = fr_flags;
@@ -1109,7 +1109,7 @@
 
 	is->is_ifp[out << 1] = fin->fin_ifp;
 	if (fin->fin_ifp != NULL) {
-		COPYIFNAME(fin->fin_ifp, is->is_ifname[out << 1]);
+		COPYIFNAME(fin->fin_ifp, is->is_ifname[out << 1], fr->fr_v);
 	}
 
 	/*
@@ -1864,7 +1864,7 @@
 	if (is->is_ifp[idx] == NULL &&
 	    (*is->is_ifname[idx] == '\0' || *is->is_ifname[idx] == '*')) {
 		is->is_ifp[idx] = ifp;
-		COPYIFNAME(ifp, is->is_ifname[idx]);
+		COPYIFNAME(ifp, is->is_ifname[idx], fin->fin_v);
 	}
 	fin->fin_rev = rev;
 	return is;
@@ -2610,7 +2610,7 @@
 			seq = ntohl(tcp->th_seq);
 			seq += is->is_isninc[0];
 			tcp->th_seq = htonl(seq);
-			fix_outcksum(fin, &tcp->th_sum, is->is_sumd[0]);
+			fix_outcksum(&tcp->th_sum, is->is_sumd[0]);
 		}
 	}
 	if ((is->is_flags & IS_ISNACK) != 0) {
@@ -2618,7 +2618,7 @@
 			seq = ntohl(tcp->th_seq);
 			seq += is->is_isninc[1];
 			tcp->th_seq = htonl(seq);
-			fix_outcksum(fin, &tcp->th_sum, is->is_sumd[1]);
+			fix_outcksum(&tcp->th_sum, is->is_sumd[1]);
 		}
 	}
 }
@@ -2648,7 +2648,7 @@
 			ack = ntohl(tcp->th_ack);
 			ack -= is->is_isninc[0];
 			tcp->th_ack = htonl(ack);
-			fix_incksum(fin, &tcp->th_sum, is->is_sumd[0]);
+			fix_incksum(&tcp->th_sum, is->is_sumd[0]);
 		}
 	}
 	if ((is->is_flags & IS_ISNACK) != 0) {
@@ -2656,7 +2656,7 @@
 			ack = ntohl(tcp->th_ack);
 			ack -= is->is_isninc[1];
 			tcp->th_ack = htonl(ack);
-			fix_incksum(fin, &tcp->th_sum, is->is_sumd[1]);
+			fix_incksum(&tcp->th_sum, is->is_sumd[1]);
 		}
 	}
 }
@@ -2665,7 +2665,10 @@
 /* ------------------------------------------------------------------------ */
 /* Function:    fr_statesync                                                */
 /* Returns:     Nil                                                         */
-/* Parameters:  ifp(I) - pointer to interface                               */
+/* Parameters:  action(I) - type of synchronisation to do                   */
+/*              v(I)      - IP version being sync'd (v4 or v6)              */
+/*              ifp(I)    - interface identifier associated with action     */
+/*              name(I)   - name associated with ifp parameter              */
 /*                                                                          */
 /* Walk through all state entries and if an interface pointer match is      */
 /* found then look it up again, based on its name in case the pointer has   */
@@ -2674,8 +2677,10 @@
 /* If ifp is passed in as being non-null then we are only doing updates for */
 /* existing, matching, uses of it.                                          */
 /* ------------------------------------------------------------------------ */
-void fr_statesync(ifp)
+void fr_statesync(action, v, ifp, name)
+int action, v;
 void *ifp;
+char *name;
 {
 	ipstate_t *is;
 	int i;
@@ -2690,15 +2695,48 @@
 		return;
 	}
 
-	for (is = ips_list; is; is = is->is_next) {
-		/*
-		 * Look up all the interface names in the state entry.
-		 */
-		for (i = 0; i < 4; i++) {
-			if (ifp == NULL || ifp == is->is_ifp[i])
+	switch (action)
+	{
+	case IPFSYNC_RESYNC :
+		for (is = ips_list; is; is = is->is_next) {
+			if (v != 0 && is->is_v != v)
+				continue;
+			/*
+			 * Look up all the interface names in the state entry.
+			 */
+			for (i = 0; i < 4; i++) {
 				is->is_ifp[i] = fr_resolvenic(is->is_ifname[i],
 							      is->is_v);
+			}
 		}
+		break;
+	case IPFSYNC_NEWIFP :
+		for (is = ips_list; is; is = is->is_next) {
+			if (v != 0 && is->is_v != v)
+				continue;
+			/*
+			 * Look up all the interface names in the state entry.
+			 */
+			for (i = 0; i < 4; i++) {
+				if (!strncmp(is->is_ifname[i], name,
+					     sizeof(is->is_ifname[i])))
+					is->is_ifp[i] = ifp;
+			}
+		}
+		break;
+	case IPFSYNC_OLDIFP :
+		for (is = ips_list; is; is = is->is_next) {
+			if (v != 0 && is->is_v != v)
+				continue;
+			/*
+			 * Look up all the interface names in the state entry.
+			 */
+			for (i = 0; i < 4; i++) {
+				if (is->is_ifp[i] == ifp)
+					is->is_ifp[i] = (void *)-1;
+			}
+		}
+		break;
 	}
 	RWLOCK_EXIT(&ipf_state);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/inet/ipf/misc.c	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef __hpux
+#pragma ident "@(#)$Id: misc.c,v 1.12 2003/11/29 07:11:03 darrenr Exp $"
+#else
+struct uio;
+#endif
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/stream.h>
+#include <sys/ddi.h>
+
+#ifdef	__hpux
+# define	BCOPY(a,b,c)	bcopy((caddr_t)a, (caddr_t)b, c)
+#endif
+#ifdef	sun
+# define	BCOPY(a,b,c)	bcopy((char *)a, (char *)b, c)
+#endif
+
+void mb_copydata(min, off, len, buf)
+mblk_t *min;
+size_t off, len;
+char *buf;
+{
+	u_char *s, *bp = (u_char *)buf;
+	size_t mlen, olen, clen;
+	mblk_t *m;
+
+	for (m = min; (m != NULL) && (len > 0); m = m->b_cont) {
+		if (m->b_datap->db_type != M_DATA)
+			continue;
+		s = m->b_rptr;
+		mlen = m->b_wptr - s;
+		olen = min(off, mlen);
+		if ((olen == mlen) || (olen < off)) {
+			off -= olen;
+			continue;
+		} else if (olen) {
+			off -= olen;
+			s += olen;
+			mlen -= olen;
+		}
+		clen = min(mlen, len);
+		BCOPY(s, bp, clen);
+		len -= clen;
+		bp += clen;
+	}
+}
+
+
+void mb_copyback(min, off, len, buf)
+mblk_t *min;
+size_t off, len;
+char *buf;
+{
+	u_char *s, *bp = (u_char *)buf;
+	size_t mlen, olen, clen;
+	mblk_t *m, *mp;
+
+	for (m = min, mp = NULL; (m != NULL) && (len > 0); m = m->b_cont) {
+		mp = m;
+		if (m->b_datap->db_type != M_DATA)
+			continue;
+
+		s = m->b_rptr;
+		mlen = m->b_wptr - s;
+		olen = min(off, mlen);
+		if ((olen == mlen) || (olen < off)) {
+			off -= olen;
+			continue;
+		} else if (olen) {
+			off -= olen;
+			s += olen;
+			mlen -= olen;
+		}
+		clen = min(mlen, len);
+		BCOPY(bp, s, clen);
+		len -= clen;
+		bp += clen;
+	}
+
+	if ((m == NULL) && (mp != NULL)) {
+		if (len > 0) {
+			mlen = mp->b_datap->db_lim - mp->b_wptr;
+			if (mlen > 0) {
+				if (mlen > len)
+					mlen = len;
+				BCOPY(bp, mp->b_wptr, mlen);
+				bp += mlen;
+				len -= mlen;
+				mp->b_wptr += mlen;
+#ifdef  STRUIO_IP
+# if SOLARIS2 < 10
+				mp->b_datap->db_struiolim = mp->b_wptr;
+# endif
+				mp->b_datap->db_struioflag &= ~STRUIO_IP;
+#endif
+			}
+		}
+
+		if (len > 0) {
+			m = allocb(len, BPRI_MED);
+			if (m != NULL) {
+				BCOPY(bp, m->b_wptr, len);
+				m->b_band = mp->b_band;
+				m->b_wptr += len;
+				linkb(mp, m);
+			}
+		}
+	}
+}
--- a/usr/src/uts/common/inet/ipf/netinet/ip_compat.h	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ipf/netinet/ip_compat.h	Fri Oct 20 16:37:58 2006 -0700
@@ -202,6 +202,28 @@
 };
 # endif /* SOLARIS2 >= 8 */
 
+# ifdef FW_HOOKS
+
+#  define	SOLARIS_PFHOOKS	1
+
+typedef	struct	qpktinfo	{
+	/* data that changes per-packet */
+	void		*qpi_ill;	/* COPIED */
+	mblk_t		*qpi_m;
+	void		*qpi_data;	/* where layer 3 header starts */
+	size_t		qpi_off;
+	int		qpi_flags;
+} qpktinfo_t;
+
+#define	QPI_NOCKSUM	0x01
+
+extern net_data_t ipf_ipv4;
+extern net_data_t ipf_ipv6;
+
+extern void mb_copydata __P((mblk_t *, size_t , size_t, char *));
+extern void mb_copyback __P((mblk_t *, size_t , size_t, char *));
+# endif
+
 # if SOLARIS2 >= 6
 #  include <sys/atomic.h>
 typedef	uint32_t	u_32_t;
@@ -213,8 +235,6 @@
 # ifdef _KERNEL
 #  define	KRWLOCK_T		krwlock_t
 #  define	KMUTEX_T		kmutex_t
-#  include "qif.h"
-#  include "pfil.h"
 #  if SOLARIS2 >= 6
 #   if SOLARIS2 == 6
 #    define	ATOMIC_INCL(x)		atomic_add_long((uint32_t*)&(x), 1)
@@ -269,16 +289,12 @@
 #  define	KMALLOC(a,b)	(a) = (b)kmem_alloc(sizeof(*(a)), KM_NOSLEEP)
 #  define	KMALLOCS(a,b,c)	(a) = (b)kmem_alloc((c), KM_NOSLEEP)
 #  define	GET_MINOR(x)	getminor(x)
-extern	void	*get_unit __P((char *, int));
-#  define	GETIFP(n, v)	get_unit(n, v)
-#  define	IFNAME(x)	((qif_t *)x)->qf_name
-#  define	COPYIFNAME(x, b) \
-				(void) strncpy(b, ((qif_t *)x)->qf_name, \
-					       LIFNAMSIZ)
-#ifdef	IRE_ILL_CN
-extern kmutex_t s_ill_g_head_lock;
-extern struct s_ill_s *s_ill_g_head;	/* ILL List Head */
-#endif /* IRE_ILL_CN */
+extern	phy_if_t	get_unit __P((char *, int));
+#  define	GETIFP(n, v)	(void *)get_unit(n, v)
+#  define	IFNAME(x)	((ill_t *)x)->ill_name
+#  define	COPYIFNAME(x, b, v)	(void) net_getifname(((v) == 4) ? \
+					    ipf_ipv4 : ipf_ipv6, \
+					    (phy_if_t)(x), (b), sizeof(b))
 #  define	GETKTIME(x)	uniqtime((struct timeval *)x)
 #  define	MSGDSIZE(x)	msgdsize(x)
 #  define	M_LEN(x)	((x)->b_wptr - (x)->b_rptr)
@@ -287,7 +303,7 @@
 #  define	MTYPE(m)	((m)->b_datap->db_type)
 #  define	FREE_MB_T(m)	freemsg(m)
 #  define	m_next		b_cont
-#  define	CACHE_HASH(x)	(((qpktinfo_t *)(x)->fin_qpi)->qpi_num & 7)
+#  define	CACHE_HASH(x)	(((phy_if_t)(x)->fin_ifp) & 7)
 #  define	IPF_PANIC(x,y)	if (x) { printf y; cmn_err(CE_PANIC, "ipf_panic"); }
 typedef mblk_t mb_t;
 # endif /* _KERNEL */
@@ -446,9 +462,9 @@
 extern	void	*get_unit __P((char *, int));
 #  define	GETIFP(n, v)	get_unit(n, v)
 #  define	IFNAME(x, b)	((ill_t *)x)->ill_name
-#  define	COPYIFNAME(x, b) \
-				(void) strncpy(b, ((qif_t *)x)->qf_name, \
-					       LIFNAMSIZ)
+#  define	COPYIFNAME(x, b, v) \
+				strncpy(b, ((ifinfo_t *)x)->ifi_name, \
+					LIFNAMSIZ)
 #  define	UIOMOVE(a,b,c,d)	uiomove((caddr_t)a,b,c,d)
 #  define	SLEEP(id, n)	{ lock_t *_l = get_sleep_lock((caddr_t)id); \
 				  sleep(id, PZERO+1); \
@@ -472,7 +488,7 @@
 #  define	IPF_PANIC(x,y)	if (x) { printf y; panic("ipf_panic"); }
 typedef mblk_t mb_t;
 
-#  define	CACHE_HASH(x)	(((qpktinfo_t *)(x)->fin_qpi)->qpi_num & 7)
+#  define	CACHE_HASH(x)	(((phy_if_t)(x)->fin_ifp) & 7)
 
 #  include "qif.h"
 #  include "pfil.h"
@@ -759,7 +775,7 @@
 # endif /* _KERNEL */
 # if (NetBSD <= 1991011) && (NetBSD >= 199606)
 #  define	IFNAME(x)	((struct ifnet *)x)->if_xname
-#  define	COPYIFNAME(x, b) \
+#  define	COPYIFNAME(x, b, v) \
 				(void) strncpy(b, \
 					       ((struct ifnet *)x)->if_xname, \
 					       LIFNAMSIZ)
@@ -980,7 +996,7 @@
 # endif /* _KERNEL */
 # if (OpenBSD >= 199603)
 #  define	IFNAME(x, b)	((struct ifnet *)x)->if_xname
-#  define	COPYIFNAME(x, b) \
+#  define	COPYIFNAME(x, b, v) \
 				(void) strncpy(b, \
 					       ((struct ifnet *)x)->if_xname, \
 					       LIFNAMSIZ)
@@ -1500,6 +1516,15 @@
 extern void eMrwlock_write_enter __P((eMrwlock_t *, char *, int));
 extern void eMrwlock_downgrade __P((eMrwlock_t *, char *, int));
 
+#undef NET_IS_HCK_L3_FULL
+#define	NET_IS_HCK_L3_FULL(n, x) (0)
+#undef NET_IS_HCK_L3_PART
+#define	NET_IS_HCK_L3_PART(n, x) (0)
+#undef NET_IS_HCK_L4_FULL
+#define	NET_IS_HCK_L4_FULL(n, x) (0)
+#undef NET_IS_HCK_L4_PART
+#define	NET_IS_HCK_L4_PART(n, x) (0)
+
 #endif
 
 #define	MAX_IPV4HDR	((0xf << 2) + sizeof(struct icmp) + sizeof(ip_t) + 8)
@@ -1638,7 +1663,7 @@
 #ifndef	COPYIFNAME
 # define	NEED_FRGETIFNAME
 extern	char	*fr_getifname __P((struct ifnet *, char *));
-# define	COPYIFNAME(x, b) \
+# define	COPYIFNAME(x, b, v) \
 				fr_getifname((struct ifnet *)x, b)
 #endif
 
--- a/usr/src/uts/common/inet/ipf/netinet/ip_fil.h	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ipf/netinet/ip_fil.h	Fri Oct 20 16:37:58 2006 -0700
@@ -61,6 +61,7 @@
 # define	SIOCIPFGET	_IOWR('r', 88, struct ipfobj)
 # define	SIOCIPFSET	_IOWR('r', 89, struct ipfobj)
 # define	SIOCIPFL6	_IOWR('r', 90, int)
+# define	SIOCIPFLP	_IOWR('r', 91, int)
 #else
 # define	SIOCADAFR	_IOW(r, 60, struct ipfobj)
 # define	SIOCRMAFR	_IOW(r, 61, struct ipfobj)
@@ -93,6 +94,7 @@
 # define	SIOCIPFGET	_IOWR(r, 88, struct ipfobj)
 # define	SIOCIPFSET	_IOWR(r, 89, struct ipfobj)
 # define	SIOCIPFL6	_IOWR(r, 90, int)
+# define	SIOCIPFLP	_IOWR(r, 91, int)
 #endif
 #define	SIOCADDFR	SIOCADAFR
 #define	SIOCDELFR	SIOCRMAFR
@@ -1147,6 +1149,14 @@
 
 
 /*
+ * sync commands
+ */
+#define	IPFSYNC_RESYNC	0
+#define	IPFSYNC_NEWIFP	1
+#define	IPFSYNC_OLDIFP	2
+
+
+/*
 ** HPUX Port
 */
 #ifdef __hpux
@@ -1352,7 +1362,7 @@
 extern	int		fr_delipftune __P((ipftuneable_t *));
 
 extern	int	frflush __P((minor_t, int, int));
-extern	void	frsync __P((void *));
+extern	void	frsync __P((int, int, void *, char *));
 extern	frgroup_t *fr_addgroup __P((char *, void *, u_32_t, minor_t, int));
 extern	int	fr_derefrule __P((frentry_t **));
 extern	void	fr_delgroup __P((char *, minor_t, int));
--- a/usr/src/uts/common/inet/ipf/netinet/ip_irc_pxy.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ipf/netinet/ip_irc_pxy.c	Fri Oct 20 16:37:58 2006 -0700
@@ -369,7 +369,7 @@
 		sum2 -= sum1;
 		sum2 = (sum2 & 0xffff) + (sum2 >> 16);
 
-		fix_outcksum(fin, &ip->ip_sum, sum2);
+		fix_outcksum(&ip->ip_sum, sum2);
 #endif
 		ip->ip_len += inc;
 	}
--- a/usr/src/uts/common/inet/ipf/netinet/ip_nat.h	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ipf/netinet/ip_nat.h	Fri Oct 20 16:37:58 2006 -0700
@@ -79,7 +79,6 @@
 #ifndef	APR_LABELLEN
 #define	APR_LABELLEN	16
 #endif
-#define	NAT_HW_CKSUM	0x80000000
 
 #define	DEF_NAT_AGE	1200     /* 10 minutes (600 seconds) */
 
@@ -428,7 +427,8 @@
 extern	u_int	fr_nat_maxbucket;
 extern	u_int	fr_nat_maxbucket_reset;
 extern	int	fr_nat_lock;
-extern	void	fr_natsync __P((void *));
+extern	void	fr_nataddrsync __P((void *, struct in_addr *));
+extern	void	fr_natifpsync __P((int, void *, char *));
 extern	u_long	fr_defnatage;
 extern	u_long	fr_defnaticmpage;
 extern	u_long	fr_defnatipage;
@@ -468,8 +468,8 @@
 extern	void	fr_natunload __P((void));
 extern	void	fr_natexpire __P((void));
 extern	void	nat_log __P((struct nat *, u_int));
-extern	void	fix_incksum __P((fr_info_t *, u_short *, u_32_t));
-extern	void	fix_outcksum __P((fr_info_t *, u_short *, u_32_t));
+extern	void	fix_incksum __P((u_short *, u_32_t));
+extern	void	fix_outcksum __P((u_short *, u_32_t));
 extern	void	fr_natderef __P((nat_t **));
 extern	u_short	*nat_proto __P((fr_info_t *, nat_t *, u_int));
 extern	void	nat_update __P((fr_info_t *, nat_t *, ipnat_t *));
--- a/usr/src/uts/common/inet/ipf/netinet/ip_state.h	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ipf/netinet/ip_state.h	Fri Oct 20 16:37:58 2006 -0700
@@ -248,7 +248,7 @@
 extern	ipstate_t *fr_addstate __P((fr_info_t *, ipstate_t **, u_int));
 extern	frentry_t *fr_checkstate __P((struct fr_info *, u_32_t *));
 extern	ipstate_t *fr_stlookup __P((fr_info_t *, tcphdr_t *, ipftq_t **));
-extern	void	fr_statesync __P((void *));
+extern	void	fr_statesync __P((int, int, void *, char *));
 extern	void	fr_timeoutstate __P((void));
 extern	int	fr_tcp_age __P((struct ipftqent *, struct fr_info *,
 				struct ipftq *, int));
--- a/usr/src/uts/common/inet/ipf/solaris.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/ipf/solaris.c	Fri Oct 20 16:37:58 2006 -0700
@@ -25,7 +25,6 @@
 #include <sys/stat.h>
 #include <sys/cred.h>
 #include <sys/dditypes.h>
-#include <sys/stream.h>
 #include <sys/poll.h>
 #include <sys/autoconf.h>
 #include <sys/byteorder.h>
@@ -34,6 +33,8 @@
 #include <sys/stropts.h>
 #include <sys/kstat.h>
 #include <sys/sockio.h>
+#include <sys/neti.h>
+#include <sys/hook.h>
 #include <net/if.h>
 #if SOLARIS2 >= 6
 # include <net/if_types.h>
@@ -59,7 +60,6 @@
 #include "netinet/ip_auth.h"
 #include "netinet/ip_state.h"
 
-
 extern	struct	filterstats	frstats[];
 extern	int	fr_running;
 extern	int	fr_flags;
@@ -74,7 +74,6 @@
 #endif
 static	int	ipf_attach __P((dev_info_t *, ddi_attach_cmd_t));
 static	int	ipf_detach __P((dev_info_t *, ddi_detach_cmd_t));
-static	int	fr_qifsync __P((ip_t *, int, void *, int, void *, mblk_t **));
 static	int	ipf_property_update __P((dev_info_t *));
 static	char	*ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME,
 				    IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME,
@@ -223,6 +222,9 @@
 	{ "ip upd. fail",		KSTAT_DATA_ULONG }
 };
 
+net_data_t ipf_ipv4;
+net_data_t ipf_ipv6;
+
 kstat_t		*ipf_kstatp[2] = {NULL, NULL};
 static int	ipf_kstat_update(kstat_t *ksp, int rwflag);
 
@@ -312,7 +314,9 @@
 	int ipfinst;
 
 	ipf_kstat_init();
+
 	ipfinst = mod_install(&modlink1);
+	
 	if (ipfinst != 0)
 		ipf_kstat_fini();
 #ifdef	IPFDEBUG
@@ -332,6 +336,7 @@
 #endif
 	if (ipfinst == 0)
 		ipf_kstat_fini();
+
 	return ipfinst;
 }
 
@@ -375,12 +380,6 @@
 	cmn_err(CE_NOTE, "IP Filter: ipf_attach(%x,%x)", dip, cmd);
 #endif
 
-	if ((pfilinterface != PFIL_INTERFACE) || (PFIL_INTERFACE < 2000000)) {
-		cmn_err(CE_NOTE, "pfilinterface(%d) != %d\n", pfilinterface,
-			PFIL_INTERFACE);
-		return EINVAL;
-	}
-
 	switch (cmd)
 	{
 	case DDI_ATTACH:
@@ -427,18 +426,6 @@
 			goto attach_failed;
 		}
 
-		if (pfil_add_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet4))
-			cmn_err(CE_WARN, "IP Filter: %s(pfh_inet4) failed",
-				"pfil_add_hook");
-#ifdef USE_INET6
-		if (pfil_add_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet6))
-			cmn_err(CE_WARN, "IP Filter: %s(pfh_inet6) failed",
-				"pfil_add_hook");
-#endif
-		if (pfil_add_hook(fr_qifsync, PFIL_IN|PFIL_OUT, &pfh_sync))
-			cmn_err(CE_WARN, "IP Filter: %s(pfh_sync) failed",
-				"pfil_add_hook");
-
 		fr_timer_id = timeout(fr_slowtimer, NULL,
 				      drv_usectohz(500000));
 
@@ -481,7 +468,7 @@
 		if (fr_refcnt != 0)
 			return DDI_FAILURE;
 
-		if (fr_running == -2 || fr_running == 0)
+		if (fr_running == -2)
 			break;
 		/*
 		 * Make sure we're the only one's modifying things.  With
@@ -492,20 +479,16 @@
 			RWLOCK_EXIT(&ipf_global);
 			return DDI_FAILURE;
 		}
+		/*
+		 * Make sure there is no active filter rule.
+		 */
+		if (ipfilter[0][fr_active] || ipfilter[1][fr_active] ||
+		    ipfilter6[0][fr_active] || ipfilter6[1][fr_active]) {
+		    RWLOCK_EXIT(&ipf_global);
+			return DDI_FAILURE;
+		}
 		fr_running = -2;
 
-		if (pfil_remove_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet4))
-			cmn_err(CE_WARN, "IP Filter: %s(pfh_inet4) failed",
-				"pfil_remove_hook");
-#ifdef USE_INET6
-		if (pfil_remove_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet6))
-			cmn_err(CE_WARN, "IP Filter: %s(pfh_inet6) failed",
-				"pfil_add_hook");
-#endif
-		if (pfil_remove_hook(fr_qifsync, PFIL_IN|PFIL_OUT, &pfh_sync))
-			cmn_err(CE_WARN, "IP Filter: %s(pfh_sync) failed",
-				"pfil_remove_hook");
-
 		RWLOCK_EXIT(&ipf_global);
 
 		if (fr_timer_id != 0) {
@@ -577,41 +560,6 @@
 
 
 /*
- * look for bad consistancies between the list of interfaces the filter knows
- * about and those which are currently configured.
- */
-/*ARGSUSED*/
-static int fr_qifsync(ip, hlen, il, out, qif, mp)
-ip_t *ip;
-int hlen;
-void *il;
-int out;
-void *qif;
-mblk_t **mp;
-{
-
-	frsync(qif);
-	/*
-	 * Resync. any NAT `connections' using this interface and its IP #.
-	 */
-	fr_natsync(qif);
-	fr_statesync(qif);
-	return 0;
-}
-
-
-/*
- * look for bad consistancies between the list of interfaces the filter knows
- * about and those which are currently configured.
- */
-int ipfsync()
-{
-	frsync(NULL);
-	return 0;
-}
-
-
-/*
  * Fetch configuration file values that have been entered into the ipf.conf
  * driver file.
  */
--- a/usr/src/uts/common/inet/pfil/compat.h	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2003 by Darren Reed.
- *
- * See the IPFILTER.LICENCE file for details on licencing.
- */
-#ifdef DEBUG
-# define	PFILDEBUG
-#endif
-
-#include "os.h"
-
-#ifndef	MTYPE
-# define	MTYPE(m)	((m)->b_datap->db_type)
-#endif
-
-#ifndef	MLEN
-# define	MLEN(m)		((m)->b_wptr - (m)->b_rptr)
-#endif
-
-#ifndef	MIN
-# define	MIN(a,b)	(((a)<(b))?(a):(b))
-#endif
-
-#ifndef ALIGN32
-# define	ALIGN32(x)      (x)
-#endif
-
-#ifdef  PFILDEBUG
-# define	PRINT(l,x)	do {if ((l) <= pfildebug) cmn_err x; } while (0)
-# define	QTONM(x)	(((x) && (x)->q_ptr) ? \
-				 ((qif_t *)(x)->q_ptr)->qf_name : "??")
-#else
-# define	PRINT(l,x)	;
-#endif
-
-#ifndef	LIFNAMSIZ
-# define	LIFNAMSIZ	32
-#endif
-
-#ifndef	ASSERT
-# define	ASSERT(x)
-#endif
-
-/*
- * The list of SAPs below all come from Sun's <atm/iftypes.h> file.  It's not
- * yet clear whether pfil should deal with any of these or not.
- */
-#ifndef	IFMP_SAP
-# define	IFMP_SAP	0x0065
-#endif
-
-#ifndef	LANER_SAP
-# define	LANER_SAP	0x9999
-#endif
-
-#ifndef	SNMP_SAP
-# define	SNMP_SAP	0x999a
-#endif
-
-#ifndef	ILMI_SAP
-# define	ILMI_SAP	0x999b
-#endif
-
-#ifndef	SIG_SAP
-# define	SIG_SAP		0x999c
-#endif
-
-#ifndef	Q93B_MGMT_SAP
-# define	Q93B_MGMT_SAP	0x999d
-#endif
-
-#ifndef	UTIL_SAP
-# define	UTIL_SAP	0x999e
-#endif
-
-#ifndef	ERROR_SAP
-# define	ERROR_SAP	0x999f
-#endif
--- a/usr/src/uts/common/inet/pfil/misc.c	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2003 by Darren Reed.
- *
- * See the IPFILTER.LICENCE file for details on licencing.
- */
-#ifndef __hpux
-#pragma ident "@(#)$Id: misc.c,v 1.12 2003/11/29 07:11:03 darrenr Exp $"
-#else
-struct uio;
-#endif
-
-#include <sys/systm.h>
-#include <sys/types.h>
-#include <sys/stream.h>
-
-#include "compat.h"
-
-#ifdef	__hpux
-# define	BCOPY(a,b,c)	bcopy((caddr_t)a, (caddr_t)b, c)
-#endif
-#ifdef	sun
-# define	BCOPY(a,b,c)	bcopy((char *)a, (char *)b, c)
-#endif
-
-void mb_copydata(min, off, len, buf)
-mblk_t *min;
-size_t off, len;
-char *buf;
-{
-	u_char *s, *bp = (u_char *)buf;
-	size_t mlen, olen, clen;
-	mblk_t *m;
-
-	for (m = min; (m != NULL) && (len > 0); m = m->b_cont) {
-		if (MTYPE(m) != M_DATA)
-			continue;
-		s = m->b_rptr;
-		mlen = m->b_wptr - s;
-		olen = MIN(off, mlen);
-		if ((olen == mlen) || (olen < off)) {
-			off -= olen;
-			continue;
-		} else if (olen) {
-			off -= olen;
-			s += olen;
-			mlen -= olen;
-		}
-		clen = MIN(mlen, len);
-		BCOPY(s, bp, clen);
-		len -= clen;
-		bp += clen;
-	}
-}
-
-
-void mb_copyback(min, off, len, buf)
-mblk_t *min;
-size_t off, len;
-char *buf;
-{
-	u_char *s, *bp = (u_char *)buf;
-	size_t mlen, olen, clen;
-	mblk_t *m, *mp;
-
-	for (m = min, mp = NULL; (m != NULL) && (len > 0); m = m->b_cont) {
-		mp = m;
-		if (MTYPE(m) != M_DATA)
-			continue;
-
-		s = m->b_rptr;
-		mlen = m->b_wptr - s;
-		olen = MIN(off, mlen);
-		if ((olen == mlen) || (olen < off)) {
-			off -= olen;
-			continue;
-		} else if (olen) {
-			off -= olen;
-			s += olen;
-			mlen -= olen;
-		}
-		clen = MIN(mlen, len);
-		BCOPY(bp, s, clen);
-		len -= clen;
-		bp += clen;
-	}
-
-	if ((m == NULL) && (mp != NULL)) {
-		if (len > 0) {
-			mlen = mp->b_datap->db_lim - mp->b_wptr;
-			if (mlen > 0) {
-				if (mlen > len)
-					mlen = len;
-				bcopy((char *)bp, (char *)mp->b_wptr, mlen);
-				bp += mlen;
-				len -= mlen;
-				mp->b_wptr += mlen;
-#ifdef  STRUIO_IP
-# if SOLARIS2 < 10
-				mp->b_datap->db_struiolim = mp->b_wptr;
-# endif
-				mp->b_datap->db_struioflag &= ~STRUIO_IP;
-#endif
-			}
-		}
-
-		if (len > 0) {
-			m = allocb(len, BPRI_MED);
-			if (m != NULL) {
-				bcopy((char *)bp, (char *)m->b_wptr, len);
-				m->b_band = mp->b_band;
-				m->b_wptr += len;
-				linkb(mp, m);
-			}
-		}
-	}
-}
--- a/usr/src/uts/common/inet/pfil/ndd.c	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,442 +0,0 @@
-/*
- * Copyright (C) 2003 by Darren Reed.
- *
- * See the IPFILTER.LICENCE file for details on licencing.
- *
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <sys/types.h>
-#include <sys/cmn_err.h>
-#include <sys/stream.h>
-#include <sys/errno.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-
-#include "compat.h"
-#include "qif.h"
-#include "pfil.h"
-
-caddr_t	pfil_nd;
-
-#if !defined(sun) || SOLARIS2 <= 8
-static int qif_report(queue_t *, mblk_t *, caddr_t);
-static int sill_report(queue_t *, mblk_t *, caddr_t);
-static int qif_ipmp_report(queue_t *, mblk_t *, caddr_t);
-static int qif_ipmp_set(queue_t *, mblk_t *, char *, caddr_t);
-static int pfil_hl_set(queue_t *, mblk_t *, char *, caddr_t);
-
-extern int pfil_report(queue_t *, mblk_t *, caddr_t);
-#else
-static int qif_report(queue_t *, mblk_t *, caddr_t, cred_t *);
-static int sill_report(queue_t *, mblk_t *, caddr_t, cred_t *);
-static int qif_ipmp_report(queue_t *, mblk_t *, caddr_t, cred_t *);
-static int qif_ipmp_set(queue_t *, mblk_t *, char *, caddr_t , cred_t *);
-static int pfil_hl_set(queue_t *, mblk_t *, char *, caddr_t , cred_t *);
-
-extern int pfil_report(queue_t *, mblk_t *, caddr_t, cred_t *);
-#endif
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_nd_get                                                 */
-/* Returns:     int     - 0 == success                                      */
-/* Parameters:  q(I)    - pointer to queue                                  */
-/*              mp(I)   - pointer to mblk                                   */
-/*              ptr(I)  - pointer to value to retrieve                      */
-/*              cred(I) - pointer to credential information                 */
-/*                                                                          */
-/* Given a pointer "ptr" to some data to return, copy it into the mblk that */
-/* has been provided.                                                       */
-/* ------------------------------------------------------------------------ */
-#if !defined(sun) || SOLARIS2 <= 8
-/*ARGSUSED*/
-int pfil_nd_get(queue_t *q, mblk_t *mp, caddr_t ptr)
-#else
-/*ARGSUSED*/
-int pfil_nd_get(queue_t *q, mblk_t *mp, caddr_t ptr, cred_t *cred)
-#endif
-{
-	int *ip;
-
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(2,(CE_CONT, "pfil_nd_get(%p,%p,%p)\n",
-		 (void *)q, (void *)mp, (void *)ptr));
-	ip = (int *)ptr;
-	(void) mi_mpprintf(mp, "%d", *ip);
-	return 0;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_nd_set                                                 */
-/* Returns:     int     - 0 == success, > 0 error occurred                  */
-/* Parameters:  q(I)    - pointer to queue                                  */
-/*              mp(I)   - pointer to mblk                                   */
-/*              str(I)  - pointer to new value as a string                  */
-/*              ptr(I)  - pointer to value to be stored                     */
-/*              cred(I) - pointer to credential information                 */
-/*                                                                          */
-/* Given a pointer "ptr" to a location to store the new value represented   */
-/* by the string "str", check to see if we allow setting that variable and  */
-/* if the new value is within the definable ranges understood for it.       */
-/* ------------------------------------------------------------------------ */
-#if !defined(sun) || SOLARIS2 <= 8
-/*ARGSUSED*/
-int pfil_nd_set(queue_t *q, mblk_t *mp, char *str, caddr_t ptr)
-#else
-/*ARGSUSED*/
-int pfil_nd_set(queue_t *q, mblk_t *mp, char *str, caddr_t ptr, cred_t *cred)
-#endif
-{
-	char *end;
-	long i;
-
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(2, (CE_CONT, "pfil_nd_set(%p,%p,%s[%p],%p)\n", 
-		  (void *)q, (void *)mp, str, (void *)str, 
-		  (void *)ptr));
-
-#if (SOLARIS2 >= 10)
-	if (ddi_strtol(str, &end, 10, &i) != 0)
-		return (EINVAL);
-#else
-	i =  mi_strtol(str, &end, 10);
-#endif
-
-	if (ptr == (caddr_t)&pfildebug) {
-#ifdef	PFILDEBUG
-#if (SOLARIS2 >= 10)
-		if ((end == str) || (i < 0) || (i > 100))
-#else
-		if (i < 0 || i > 1)
-#endif
-#endif
-			return EINVAL;
-	} else if (ptr == (caddr_t)&qif_verbose) {
-		if ((end == str) || (i < 0) || (i > 1))
-			return EINVAL;
-	}
-	*((int *)ptr) = i;
-	return 0;
-}
-
-
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_ioctl_nd                                               */
-/* Returns:     int - B_TRUE == success, B_FALSE == getset error            */
-/* Parameters:  q(I)    - pointer to queue                                  */
-/*              mp(I)   - pointer to mblk                                   */
-/*                                                                          */
-/* Handle both incoming ndd set and get requests but only if they're not    */
-/* destined for another STREAMS module (ie. there is no next queue for this */
-/* message.)                                                                */
-/* ------------------------------------------------------------------------ */
-int pfil_ioctl_nd(queue_t *q, mblk_t *mp)
-{
-	return (nd_getset(q, pfil_nd, mp));
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_nd_init                                                */
-/* Returns:     int   - 0 == success, -1 == error                           */
-/* Parameters:  None.                                                       */
-/*                                                                          */
-/* Perform any initialisation required for processing ndd ioctl messages.   */
-/* ------------------------------------------------------------------------ */
-int pfil_nd_init()
-{
-
-#ifdef PFILDEBUG
-	if (!nd_load(&pfil_nd, "pfildebug", pfil_nd_get, pfil_nd_set,
-		      (caddr_t)&pfildebug)) {
-		nd_free(&pfil_nd);
-		return -1;
-	}
-#endif
-
-	if (!nd_load(&pfil_nd, "pfil_delayed_copy", pfil_nd_get, pfil_nd_set,
-		     (caddr_t)&pfil_delayed_copy)) {
-		nd_free(&pfil_nd);
-		return -1;
-	}
-
-	if (!nd_load(&pfil_nd, "pfil_interface", pfil_nd_get, NULL,
-		     (caddr_t)&pfilinterface)) {
-		nd_free(&pfil_nd);
-		return -1;
-	}
-
-	if (!nd_load(&pfil_nd, "qif_status", qif_report, NULL, NULL)) {
-		nd_free(&pfil_nd);
-		return -1;
-	}
-
-	if (!nd_load(&pfil_nd, "sill_status", sill_report, NULL, NULL)) {
-		nd_free(&pfil_nd);
-		return -1;
-	}
-
-	if (!nd_load(&pfil_nd, "qif_ipmp_status", qif_ipmp_report, NULL,
-		     NULL)) {
-		nd_free(&pfil_nd);
-		return -1;
-	}
-
-	if (!nd_load(&pfil_nd, "qif_ipmp_set", NULL, qif_ipmp_set, NULL)) {
-		nd_free(&pfil_nd);
-		return -1;
-	}
-
-	if (!nd_load(&pfil_nd, "qif_verbose", pfil_nd_get, pfil_nd_set,
-		     (caddr_t)&qif_verbose)) {
-		nd_free(&pfil_nd);
-		return -1;
-	}
-
-	if (!nd_load(&pfil_nd, "pfil_inet4", pfil_report, NULL,
-		     (void *)&pfh_inet4)) {
-		nd_free(&pfil_nd);
-		return -1;
-	}
-
-	if (!nd_load(&pfil_nd, "pfil_inet6", pfil_report, NULL,
-		     (void *)&pfh_inet6)) {
-		nd_free(&pfil_nd);
-		return -1;
-	}
-
-	if (!nd_load(&pfil_nd, "pfil_sync", pfil_report, NULL,
-		     (void *)&pfh_sync)) {
-		nd_free(&pfil_nd);
-		return -1;
-	}
-
-	if (!nd_load(&pfil_nd, "pfil_hl", NULL, pfil_hl_set, NULL)) {
-		nd_free(&pfil_nd);
-		return -1;
-	}
-
-	return 0;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_nd_fini                                                */
-/* Returns:     void                                                        */
-/* Parameters:  None.                                                       */
-/*                                                                          */
-/* Clean up any data structures related to ndd processing in preparation    */
-/* for the module being unloaded.                                           */
-/* ------------------------------------------------------------------------ */
-void pfil_nd_fini()
-{
-
-	nd_free(&pfil_nd);
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    qif_report                                                  */
-/* Returns:     int                                                         */
-/* Parameters:  q(I)    - pointer to queue                                  */
-/*              mp(I)   - pointer to mblk                                   */
-/*              ptr(I)  - pointer to value to retrieve                      */
-/*              cred(I) - pointer to credential information                 */
-/*                                                                          */
-/* Fills the mblk with any qif data that happens to be currently available. */
-/* ------------------------------------------------------------------------ */
-#if !defined(sun) || SOLARIS2 <= 8
-/*ARGSUSED*/
-static int qif_report(queue_t *q, mblk_t *mp, caddr_t arg)
-#else
-/*ARGSUSED*/
-static int qif_report(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *cred)
-#endif
-{
-	qif_t *qif;
-
-	(void) mi_mpprintf(mp,
-		   "ifname ill q OTHERQ ipmp num sap hl nr nw bad copy copyfail drop notip nodata notdata");
-	READ_ENTER(&pfil_rw);
-	for (qif = qif_head ; qif; qif = qif->qf_next)
-		(void) mi_mpprintf(mp,
-			"%s %p %p %p %p %d %x %d %lu %lu %lu %lu %lu %lu %lu %lu %lu",
-				   qif->qf_name, (void *)qif->qf_ill,
-				   (void *)qif->qf_q, (void *)qif->qf_oq,
-				   (void *)qif->qf_ipmp, qif->qf_num,
-				   qif->qf_sap, (int)qif->qf_hl,
-				   qif->qf_nr, qif->qf_nw, qif->qf_bad,
-				   qif->qf_copy, qif->qf_copyfail,
-				   qif->qf_drop, qif->qf_notip,
-				   qif->qf_nodata, qif->qf_notdata);
-	RW_EXIT(&pfil_rw);
-	return 0;
-}
-
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    sill_report                                                 */
-/* Returns:     int                                                         */
-/* Parameters:  q(I)    - pointer to queue                                  */
-/*              mp(I)   - pointer to mblk                                   */
-/*              ptr(I)  - pointer to value to retrieve                      */
-/*              cred(I) - pointer to credential information                 */
-/*                                                                          */
-/* Fills the mblk with any shadow ill (s_illt) data that happens to be      */
-/* currently available.                                                     */
-/* ------------------------------------------------------------------------ */
-#if !defined(sun) || SOLARIS2 <= 8
-/*ARGSUSED*/
-static int sill_report(queue_t *q, mblk_t *mp, caddr_t arg)
-#else
-/*ARGSUSED*/
-static int sill_report(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *cred)
-#endif
-{
-	s_ill_t *sill;
-
-	(void) mi_mpprintf(mp,
-		   "sill name sap mtu localaddr netmask broadaddr dstaddr");
-	READ_ENTER(&pfil_rw);
-	for (sill = s_ill_g_head ; sill; sill = sill->ill_next)
-		(void) mi_mpprintf(mp, "%p %s %x %u %x %x %x %x",
-				   (void *)sill, sill->ill_name, sill->ill_sap,
-				   sill->mtu,
-				   sill->localaddr.in.sin_addr.s_addr,
-				   sill->netmask.in.sin_addr.s_addr,
-				   sill->broadaddr.in.sin_addr.s_addr,
-				   sill->dstaddr.in.sin_addr.s_addr);
-	RW_EXIT(&pfil_rw);
-	return 0;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    qif_ipmp_report                                             */
-/* Returns:     int                                                         */
-/* Parameters:  q(I)    - pointer to queue                                  */
-/*              mp(I)   - pointer to mblk                                   */
-/*              ptr(I)  - pointer to value to retrieve                      */
-/*              cred(I) - pointer to credential information                 */
-/*                                                                          */
-/* Fills the mblk with any qif data that happens to be currently available. */
-/* ------------------------------------------------------------------------ */
-#if !defined(sun) || SOLARIS2 <= 8
-/*ARGSUSED*/
-static int qif_ipmp_report(queue_t *q, mblk_t *mp, caddr_t arg)
-#else
-/*ARGSUSED*/
-static int qif_ipmp_report(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *cred)
-#endif
-{
-	qif_t *qif;
-
-	(void) mi_mpprintf(mp, "ifname members");
-	READ_ENTER(&pfil_rw);
-	for (qif = qif_head ; qif; qif = qif->qf_next) {
-		if ((qif->qf_flags & QF_IPMP) == 0)
-			continue;
-		(void) mi_mpprintf(mp, "%s %s", qif->qf_name, qif->qf_members);
-	}
-	RW_EXIT(&pfil_rw);
-	return 0;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    qif_ipmp_set                                                */
-/* Returns:     int     - 0 == success, > 0 error occurred                  */
-/* Parameters:  q(I)    - pointer to queue                                  */
-/*              mp(I)   - pointer to mblk                                   */
-/*              str(I)  - pointer to new value as a string                  */
-/*              ptr(I)  - pointer to value to be stored                     */
-/*              cred(I) - pointer to credential information                 */
-/*                                                                          */
-/* This function is a wrapper for qif_ipmp_update(), providing a run-time   */
-/* interactive way to configure the IPMP configuration for pfil without     */
-/* needing to load/unload the module to reread the config file (or is there */
-/* a way to do that once loaded, anyway?)                                   */
-/* ------------------------------------------------------------------------ */
-#if !defined(sun) || SOLARIS2 <= 8
-/*ARGSUSED*/
-static int qif_ipmp_set(queue_t *q, mblk_t *mp, char *str, caddr_t ptr)
-#else
-/*ARGSUSED*/
-static int qif_ipmp_set(queue_t *q, mblk_t *mp, char *str, caddr_t ptr,
-			cred_t *cred)
-#endif
-{
-	char *s, *t;
-
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(2, (CE_CONT, "qif_ipmp_set(0x%p,0x%p,0x%s[%p],0x%p)\n",
-		  (void *)q, (void *)mp, str, (void *)str, (void *)ptr));
-
-	t = NULL;
-	s = str;
-	do {
-		if (t != NULL)
-			s = t + 1;
-		t = strchr(s, ';');
-		if (t != NULL)
-			*t = '\0';
-		qif_ipmp_update(s);
-	} while (t != NULL);
-
-	return 0;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_hl_set                                                 */
-/* Returns:     int     - 0 == success, > 0 error occurred                  */
-/* Parameters:  q(I)    - pointer to queue                                  */
-/*              mp(I)   - pointer to mblk                                   */
-/*              str(I)  - pointer to new value as a string                  */
-/*              ptr(I)  - pointer to value to be stored                     */
-/*              cred(I) - pointer to credential information                 */
-/*                                                                          */
-/* Explicitly set the header length (hl) field of the qif structure.  This  */
-/* is used in situations where pfil cannot, for some reason, automatically  */
-/* determine it via either ioctl snooping or looking at passing messages.   */
-/* ndd -set /dev/pfil pfil_hl ipmp0=14  or v4:ipmp0=14                      */
-/* ------------------------------------------------------------------------ */
-#if !defined(sun) || SOLARIS2 <= 8
-/*ARGSUSED*/
-static int pfil_hl_set(queue_t *q, mblk_t *mp, char *str, caddr_t ptr)
-#else
-/*ARGSUSED*/
-static int pfil_hl_set(queue_t *q, mblk_t *mp, char *str, caddr_t ptr,
-			cred_t *cred)
-#endif
-{
-	char *s, *t;
-
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(2, (CE_CONT, "pfil_hl_set(0x%lx,0x%lx,0x%lx[%s],0x%lx)\n",
-		  (u_long)q, (u_long)mp, (u_long)str, str, (u_long)ptr));
-
-	t = NULL;
-	s = str;
-	do {
-		if (t != NULL)
-			s = t + 1;
-		t = strchr(s, ';');
-		if (t != NULL)
-			*t = '\0';
-		qif_hl_set(s);
-	} while (t != NULL);
-
-	return 0;
-}
--- a/usr/src/uts/common/inet/pfil/os.h	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2003 by Darren Reed.
- *
- * See the IPFILTER.LICENCE file for details on licencing.
- */
-#include <sys/sunddi.h>
-#include <sys/ddi.h>
-#if SOLARIS2 >= 6
-# include <net/if_types.h>
-#endif
-#undef	IPOPT_EOL
-#undef	IPOPT_NOP
-#undef	IPOPT_LSRR
-#undef	IPOPT_RR
-#undef	IPOPT_SSRR
-
-#include <inet/common.h>
-#include <inet/mi.h>
-#include <inet/led.h>
-#include <inet/nd.h>
-#if SOLARIS2 >= 8
-# include <netinet/ip6.h>
-#endif
-#include <inet/ip.h>
-
-#define	MUTEX_ENTER(x)		mutex_enter(x)
-#define	MUTEX_EXIT(x)		mutex_exit(x)
-#define	READ_ENTER(x)		rw_enter(x, RW_READER)
-#define	WRITE_ENTER(x)		rw_enter(x, RW_WRITER)
-#define	RW_DOWNGRADE(x)		rw_downgrade(x)
-#define	RW_EXIT(x)		rw_exit(x)
-#define	KMALLOC(v,t,z,w)	(v) = (t)kmem_zalloc(z, w)
-#define	KMFREE(v, z)		kmem_free(v, z)
-
-extern	caddr_t			pfil_nd;
-
-#if defined(atomic_add_long) && (SOLARIS2 < 7)
-# undef atomic_add_long
-# define atomic_add_long(x,y)	atomic_add_32((uint32_t *)x, y)
-#endif
--- a/usr/src/uts/common/inet/pfil/pfil.c	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,358 +0,0 @@
-/*
- * Copyright (C) 2000, 2003 by Darren Reed.
- *
- * See the IPFILTER.LICENCE file for details on licencing.
- *
- * ident "@(#)$Id: pfil.c,v 1.27 2003/11/30 09:45:57 darrenr Exp $"
- *
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-#ifndef __hpux
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-#else
-struct uio;
-#endif
-
-#include <sys/systm.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/errno.h>
-#include <sys/uio.h>
-#include <sys/buf.h>
-#include <sys/conf.h>
-#include <sys/cmn_err.h>
-#include <sys/stat.h>
-#include <sys/stream.h>
-#include <sys/poll.h>
-#include <sys/byteorder.h>
-#include <sys/socket.h>
-#ifdef sun
-# include <sys/kmem.h>
-#endif
-#include <sys/dlpi.h>
-#include <sys/lock.h>
-#include <sys/stropts.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#ifdef sun
-# include <inet/common.h>
-# if SOLARIS2 >= 8
-#  include <netinet/ip6.h>
-# endif
-# undef IPOPT_EOL
-# undef IPOPT_NOP
-# undef IPOPT_LSRR
-# undef IPOPT_SSRR
-# undef IPOPT_RR
-# include <inet/ip.h>
-#endif
-
-#include "compat.h"
-#include "qif.h"
-#include "pfil.h"
-
-
-int	pfil_delayed_copy = 1;
-int	pfilinterface = PFIL_INTERFACE;
-/*
-** HPUX Port
-** Align these structs to 16 bytes
-** so that the embedded locks (first member)
-** are 16 byte aligned
-*/
-#ifdef	__hpux
-#pragma align 16
-struct	pfil_head	pfh_inet4 = { 0, NULL, NULL, 0 };
-#pragma align 16
-struct	pfil_head	pfh_inet6 = { 0, NULL, NULL, 0 };
-#pragma align 16
-struct	pfil_head	pfh_sync = { 0, NULL, NULL, 0 };
-#else
-struct	pfil_head	pfh_inet4;
-struct	pfil_head	pfh_inet6;
-struct	pfil_head	pfh_sync;
-#endif
-
-
-static int pfil_list_add(pfil_list_t *,
-			 int (*) __P((struct ip *, int, void *, int,
-				      void *, mblk_t **)),
-			 int);
-static int pfil_list_remove(pfil_list_t *,
-			 int (*) __P((struct ip *, int, void *, int,
-				      void *, mblk_t **)));
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_report                                                 */
-/* Returns:     int     - always returns 0                                  */
-/* Parameters:  q(I)    - pointer to queue                                  */
-/*              mp(I)   - pointer to mblk                                   */
-/*              arg(I)  - pointer to value to retrieve                      */
-/*              cred(I) - pointer to credential information                 */
-/*                                                                          */
-/* Returns a list of the registered callbacks for processing packets going  */
-/* in and out on a particular filtering head structure                      */
-/* ------------------------------------------------------------------------ */
-#if !defined(sun) || (SOLARIS2 <= 8)
-/*ARGSUSED*/
-int pfil_report(queue_t *q, mblk_t *mp, caddr_t arg)
-#else
-/*ARGSUSED*/
-int pfil_report(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *cred)
-#endif
-{
-	packet_filter_hook_t *p;
-	pfil_head_t *ph;
-
-	ph = (pfil_head_t *)arg;
-
-	READ_ENTER(&ph->ph_lock);
-
-	(void) mi_mpprintf(mp, "in");
-	(void) mi_mpprintf(mp, "function\tflags");
-	for (p = ph->ph_in.pfl_top; p; p = p->pfil_next)
-		(void) mi_mpprintf(mp,"%p\t%x",
-				   (void *)p->pfil_func, p->pfil_flags);
-
-	(void) mi_mpprintf(mp, "out");
-	(void) mi_mpprintf(mp, "function\tflags");
-	for (p = ph->ph_out.pfl_top; p; p = p->pfil_next)
-		(void) mi_mpprintf(mp,"%p\t%x",
-				   (void *)p->pfil_func, p->pfil_flags);
-
-	RW_EXIT(&ph->ph_lock);
-
-	return 0;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_init                                                   */
-/* Returns:     void                                                        */
-/* Parameters:  ph(I) - pointer to pfil head structure                      */
-/*                                                                          */
-/* Initialise a pfil_head structure.                                        */
-/* ------------------------------------------------------------------------ */
-void
-pfil_init(ph)
-	 struct pfil_head *ph;
-{
-#ifdef sun
-	rw_init(&ph->ph_lock, "pfil head", RW_DRIVER, NULL);
-#endif
-#ifdef __hpux
-	initlock(&ph->ph_lock, PFIL_SMAJ, 1020, "pfil head");
-#endif
-	ph->ph_in.pfl_top = NULL;
-	ph->ph_in.pfl_tail = &ph->ph_in.pfl_top;
-	ph->ph_out.pfl_top = NULL;
-	ph->ph_out.pfl_tail = &ph->ph_out.pfl_top;
-	ph->ph_init = 1;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_add_hook                                               */
-/* Returns:     int      - 0 == success, else error.                        */
-/* Parameters:  func(I)  - function pointer to add                          */
-/*              flags(I) - flags describing for which events to call the    */
-/*                         passed function                                  */
-/*              ph(I)    - pointer to callback head structure               */
-/*                                                                          */
-/* This function is the public interface for adding a callback function to  */
-/* a list of callbacks for a particular protocol head (ph).                 */
-/*                                                                          */
-/* pfil_add_hook() adds a function to the packet filter hook.  the          */
-/* flags are:                                                               */
-/*	PFIL_IN		call me on incoming packets                         */
-/*	PFIL_OUT	call me on outgoing packets                         */
-/*	PFIL_WAITOK	OK to call malloc and wait whilst adding this hook  */
-/* ------------------------------------------------------------------------ */
-int
-pfil_add_hook(func, flags, ph)
-	int	(*func) __P((struct ip *, int, void *, int,
-			     void *, mblk_t **));
-	int	flags;
-	struct	pfil_head	*ph;
-{
-	int err = 0;
-
-	ASSERT((flags & ~(PFIL_IN|PFIL_OUT|PFIL_WAITOK)) == 0);
-
-	if (ph->ph_init == 0)
-		pfil_init(ph);
-
-	WRITE_ENTER(&ph->ph_lock);
-
-	if (flags & PFIL_IN)
-		err = pfil_list_add(&ph->ph_in, func, flags);
-
-	if ((err == 0) && (flags & PFIL_OUT))
-		err = pfil_list_add(&ph->ph_out, func, flags);
-
-	RW_EXIT(&ph->ph_lock);
-
-	return err;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_list_add                                               */
-/* Returns:     int      - 0 == success, else error.                        */
-/* Parameters:  list(I)  - pfil list pointer                                */
-/*              func(I)  - function pointer to add                          */
-/*              flags(I) - flags describing for which events to call the    */
-/*                         passed function                                  */
-/* Write Locks: list's owner                                                */
-/*                                                                          */
-/* Adds the function (func) to the end of the list of functions.            */
-/* ------------------------------------------------------------------------ */
-static int
-pfil_list_add(list, func, flags)
-	pfil_list_t *list;
-	int	(*func) __P((struct ip *, int, void *, int,
-			     void *, mblk_t **));
-	int flags;
-{
-	struct packet_filter_hook *pfh;
-	int wait;
-
-	for (pfh = list->pfl_top; pfh; pfh = pfh->pfil_next)
-		if (pfh->pfil_func == func)
-			return EEXIST;
-
-	wait = flags & PFIL_WAITOK ? KM_SLEEP : KM_NOSLEEP;
-
-	KMALLOC(pfh, struct packet_filter_hook *, sizeof(*pfh), wait);
-	if (pfh == NULL)
-		return ENOMEM;
-	pfh->pfil_func = func;
-	pfh->pfil_flags = flags;
-
-	/*
-	 * insert the input list in reverse order of the output list
-	 * so that the hooks are called in the reverse order for each
-	 * direction.  So if it was A,B,C for input, it is C,B,A for output.
-	 */
-
-	if (flags & PFIL_OUT) {
-		pfh->pfil_pnext = list->pfl_tail;
-		*list->pfl_tail = pfh;
-		list->pfl_tail = &pfh->pfil_next;
-	} else if (flags & PFIL_IN) {
-		pfh->pfil_pnext = &list->pfl_top;
-		pfh->pfil_next = list->pfl_top;
-		list->pfl_top = pfh;
-		if (pfh->pfil_next == NULL)
-			list->pfl_tail = &pfh->pfil_next;
-	}
-
-	return 0;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_remove_hook                                            */
-/* Returns:     int      - 0 == success, else error.                        */
-/* Parameters:  func(I)  - function pointer to remove                       */
-/*              flags(I) - flags describing for which events to call the    */
-/*                         passed function                                  */
-/*              ph(I)    - pointer to callback head structure               */
-/*                                                                          */
-/* pfil_remove_hook removes a specific function from a particular           */
-/* pfil_head's list of callbacks as given by which flags have been passed.  */
-/* ------------------------------------------------------------------------ */
-int
-pfil_remove_hook(func, flags, ph)
-	int	(*func) __P((struct ip *, int, void *, int,
-			     void *, mblk_t **));
-	int	flags;
-	struct	pfil_head	*ph;
-{
-	int err = 0;
-
-	ASSERT((flags & ~(PFIL_IN|PFIL_OUT)) == 0);
-
-	if (ph->ph_init == 0)
-		pfil_init(ph);
-
-	WRITE_ENTER(&ph->ph_lock);
-
-	if (flags & PFIL_IN)
-		err = pfil_list_remove(&ph->ph_in, func);
-
-	if ((err == 0) && (flags & PFIL_OUT))
-		err = pfil_list_remove(&ph->ph_out, func);
-
-	RW_EXIT(&ph->ph_lock);
-
-	return err;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_list_remove                                            */
-/* Returns:     int     - 0 == success, else error.                         */
-/* Parameters:  list(I) - pfil list pointer                                 */
-/*              func(I) - function pointer to remove                        */
-/* Write Locks: list's owner                                                */
-/*                                                                          */
-/* pfil_list_remove is an internal function that takes a function off the   */
-/* specified pfil list, providing that a match for func is found.           */
-/* ------------------------------------------------------------------------ */
-static int
-pfil_list_remove(list, func)
-	pfil_list_t *list;
-	int	(*func) __P((struct ip *, int, void *, int,
-			     void *, mblk_t **));
-{
-	struct packet_filter_hook *pfh;
-
-	for (pfh = list->pfl_top; pfh; pfh = pfh->pfil_next)
-		if (pfh->pfil_func == func) {
-			*pfh->pfil_pnext = pfh->pfil_next;
-			if (list->pfl_tail == &pfh->pfil_next)
-				list->pfl_tail = pfh->pfil_pnext;
-			KMFREE(pfh, sizeof(*pfh));
-			return 0;
-		}
-
-	return ESRCH;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_hook_get                                               */
-/* Returns:     struct packet_filter_hook * - pointer to first member in    */
-/*                                            list of callbacks or NULL if  */
-/*                                            if there are none.            */
-/* Parameters:  flags(I) - indicates which callback list to return          */ 
-/*              ph(I)    - pointer to callback head structure               */
-/* Locks:       READ(ph->ph_lock)                                           */
-/*                                                                          */
-/* Returns the first pointer of the list associated with "flags" or NULL if */
-/* flags is not a recognised value.                                         */
-/* ------------------------------------------------------------------------ */
-struct packet_filter_hook *
-pfil_hook_get(flag, ph)
-	int flag;
-	struct	pfil_head	*ph;
-{
-
-	/* ASSERT(rw_read_locked(&ph->ph_lock) != 0); */
-
-	if (ph->ph_init != 0) {
-		switch (flag)
-		{
-		case PFIL_IN:
-			return ph->ph_in.pfl_top;
-		case PFIL_OUT:
-			return ph->ph_out.pfl_top;
-		}
-	}
-	return NULL;
-}
--- a/usr/src/uts/common/inet/pfil/pfil.conf	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-#
-# 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 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-
-name="pfil" parent="pseudo" instance=0;
-
--- a/usr/src/uts/common/inet/pfil/pfil.h	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2003 by Darren Reed.
- *
- * See the IPFILTER.LICENCE file for details on licencing.
- *
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifndef _NET_PFIL_H_
-#define _NET_PFIL_H_
-
-#define	PFIL_RELEASE	"2.1.6"
-#define	PFIL_VERSION	2010600
-#define	PFIL_INTERFACE	2000000
-
-#ifndef __P
-# ifdef __STDC__
-#  define	__P(x)	x
-# else
-#  define	__P(x)	()
-# endif
-#endif
-
-#ifdef sun
-# include <inet/ip.h>
-# if SOLARIS2 < 9
-#  include <netinet/in_systm.h>
-#  undef IPOPT_EOL
-#  undef IPOPT_NOP
-#  undef IPOPT_RR
-#  undef IPOPT_LSRR
-#  undef IPOPT_SSRR
-#  include <netinet/ip.h>
-# endif
-#endif
-#ifdef __hpux
-# include <netinet/in_systm.h>
-# include <netinet/in.h>
-# include <netinet/ip.h>
-#endif
-
-
-typedef	struct packet_filter_hook {
-	struct	packet_filter_hook *pfil_next;
-	struct	packet_filter_hook **pfil_pnext;
-	int	(*pfil_func) __P((struct ip *, int, void *, int,
-				  void *, mblk_t **));
-	int	pfil_flags;
-} packet_filter_hook_t;
-
-
-typedef	struct	pfil_list	{
-	struct	packet_filter_hook	*pfl_top;
-	struct	packet_filter_hook	**pfl_tail;
-} pfil_list_t;
-
-
-/*
-** HP Port
-** spinlocks should be the first member for
-** alignment reason. Spinlocks need to be 16 byte 
-** aligned. The struct itself is aligned during 
-** allocation so that the spinlock starts at a
-** 16 byte boundary
-*/
-typedef struct pfil_head {
-	krwlock_t	ph_lock;
-	pfil_list_t	ph_in;
-	pfil_list_t	ph_out;
-	int	ph_init;
-} pfil_head_t;
-
-
-#define	PFIL_IN		0x00000001
-#define	PFIL_OUT	0x00000002
-#define	PFIL_INOUT	(PFIL_IN|PFIL_OUT)
-#define	PFIL_WAITOK	0x00000004
-#define	PFIL_GROUP	0x00000008
-#define	PFIL_ALL	(PFIL_IN|PFIL_OUT)
-
-/* HPUX Port Major no. for pfil spinlocks */
-#define	PFIL_SMAJ	0
-
-void	pfil_init __P((struct pfil_head *));
-struct	packet_filter_hook *pfil_hook_get __P((int, struct pfil_head *));
-int	pfil_add_hook __P((int (*func) __P((struct ip *, int, void *, int,
-					    void *, mblk_t **)), int,
-			   struct pfil_head *));
-int	pfil_remove_hook __P((int (*func) __P((struct ip *, int, void *, int,
-					    void *, mblk_t **)), int,
-			   struct pfil_head *));
-int pfil_sendbuf(mblk_t *);
-mblk_t *pfil_make_dl_packet __P((mblk_t *, struct ip *, void *,
-				 char *, queue_t **));
-void pfil_send_dl_packet __P((queue_t *, mblk_t *));
-
-
-extern	int	pfilinterface;
-extern	int	pfil_delayed_copy;
-extern	int	pfildebug;
-extern	struct	pfil_head	pfh_inet4;	/* IPv4 packet processing */
-extern	struct	pfil_head	pfh_inet6;	/* IPv6 packet processing */
-extern	struct	pfil_head	pfh_sync;	/* Notification of interface */
-						/* naming/address changes.   */
-extern	krwlock_t	qif_rwlock;
-extern	krwlock_t	pfil_rw;
-
-/*
- * NOTE: On Solaris, even though pfilwput(), etc, are prototyped as returning
- * an int, the return value is never checked and much code ignores it, anyway,
- * so for performance reasonsm, various functions return void instead of int.
- */
-extern void pfilwput __P((queue_t *q, mblk_t *mp));
-extern void pfil_ioctl __P((queue_t *q, mblk_t *mp));
-extern int pfil_ioctl_nd __P((queue_t *q, mblk_t *mp));
-extern int pfil_nd_init __P((void));
-extern void pfil_nd_fini __P((void));
-extern int pfil_precheck __P((queue_t *, mblk_t **, int, struct qif *));
-extern void pfil_startup __P((void));
-extern void pfilmodrput __P((queue_t *q, mblk_t *mp));
-extern void pfilmodwput __P((queue_t *q, mblk_t *mp));
-extern void pfilmodwsrv __P((queue_t *q));
-#ifdef USE_SERVICE_ROUTINE
-extern int pfilmodrsrv __P((queue_t *q));
-#else
-#define pfilmodrsrv  NULL
-#endif
-
-#ifdef IRE_ILL_CN
-void pfil_addif(queue_t *, const char *, int);
-#endif
-
-extern void mb_copydata __P((mblk_t *, size_t , size_t, char *));
-extern void mb_copyback __P((mblk_t *, size_t , size_t, char *));
-extern int pfildebug;
-
-void pfil_update_ifaddr(mblk_t * mp);
-#endif /* _NET_PFIL_H_ */
--- a/usr/src/uts/common/inet/pfil/pfild.h	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2003 by Darren Reed.
- *
- * See the IPFILTER.LICENCE file for details on licencing.
- *
- * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <netinet/in.h>
-
-/*
- * STREAMS control messages used to communicate between pfild and pfil.
- * Messages are sent down to /dev/pfil as M_PROTO->M_DATA.
- * M_PROTO block contains uint32_t command code.
- * M_DATA block contains [an array of] the corresponding data structure.
- */
-
-/*
- * Data structure used to pass interface configuration information from
- * pfild to the pfil kernel module.
- */
-#define	PFILCMD_IFADDRS 1
-struct pfil_ifaddrs {
-	char name[LIFNAMSIZ];
-	union {
-		struct sockaddr_in in;
-		struct sockaddr_in6 in6;
-	} localaddr;
-	union {
-		struct sockaddr_in in;
-		struct sockaddr_in6 in6;
-	} netmask;
-	union {
-		struct sockaddr_in in;
-		struct sockaddr_in6 in6;
-	} broadaddr;
-	union {
-		struct sockaddr_in in;
-		struct sockaddr_in6 in6;
-	} dstaddr;
-	uint_t mtu;
-};
-
-/*
- * Data structure used to pass interface valid source address set information
- * from pfild to the pfil kernel module.
- */
-#define	PFILCMD_IFADDRSET 2
-struct pfil_ifaddrset {
-	char name[LIFNAMSIZ];
-	uint8_t af;
-	uint32_t nspans;
-};
-struct pfil_v4span {
-	uint32_t first, last;		/* in host byte order! */
-};
-struct pfil_v6span {
-	struct in6_addr first, last;
-};
--- a/usr/src/uts/common/inet/pfil/pfildrv.c	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1171 +0,0 @@
-/*
- * Copyright (C) 2000, 2003 by Darren Reed.
- *
- * See the IPFILTER.LICENCE file for details on licencing.
- *
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <sys/conf.h>
-#include <sys/debug.h>
-#include <sys/atomic.h>
-#include <sys/ethernet.h>
-#include <sys/stream.h>
-#include <sys/errno.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <sys/cred.h>
-#include <sys/modctl.h>
-#include <sys/devops.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/stat.h>
-#include <sys/cmn_err.h>
-#include <sys/dlpi.h>
-#include <sys/kmem.h>
-#include <sys/strsun.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <inet/common.h>
-#include <inet/nd.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/tcp.h>
-#include <netinet/udp.h>
-#include <netinet/ip_icmp.h>
-#if SOLARIS2 >= 8
-# include <netinet/ip6.h>
-#endif
-#undef IPOPT_EOL
-#undef IPOPT_NOP
-#undef IPOPT_RR
-#undef IPOPT_LSRR
-#undef IPOPT_SSRR
-#include <inet/ip.h>
-#include <inet/ip_if.h>
-
-#include "compat.h"
-#include "qif.h"
-#include "pfil.h"
-
-
-#undef	USE_SERVICE_ROUTINE
-
-#define MINSDUSZ 1
-#define MAXSDUSZ INFPSZ
-
-char _depends_on[] = "drv/ip";
-
-static struct module_info pfil_minfo = {
-	0x534b, "pfil", MINSDUSZ, MAXSDUSZ, 0, 0
-};
-
-krwlock_t	pfil_rw;
-int		pfildebug = 0;
-int		pfil_installed = 0;
-
-#ifdef IRE_ILL_CN
-kmutex_t s_ill_g_head_lock;
-s_ill_t * s_ill_g_head = NULL;
-queue_t *pfildq;			/* pfild's read queue for packets */
-#endif
-
-/************************************************************************
- * STREAMS device information (/dev/pfil)
- */
-static int pfildevopen(queue_t *, dev_t *, int, int, cred_t *);
-static int pfildevclose(queue_t *, int, cred_t *);
-
-#ifdef IRE_ILL_CN
-static void pfil_remif(queue_t *q);
-static void _dump_s_ill(s_ill_t *);
-static void _dump_s_ill_all(void);
-#endif
-
-static struct qinit pfil_rinit = {
-	NULL, NULL, pfildevopen, pfildevclose, NULL, &pfil_minfo, NULL
-};
-
-static struct qinit pfil_winit = {
-	(pfi_t)pfilwput, NULL, NULL, NULL, NULL, &pfil_minfo, NULL
-};
-
-struct streamtab pfil_dev_strtab = {
-	&pfil_rinit, &pfil_winit
-};
-
-extern int nulldev();
-extern int nodev();
-
-void pfil_donotip(int, qif_t *, queue_t *, mblk_t *, mblk_t *, struct ip *, size_t);
-static int pfil_info(dev_info_t *, ddi_info_cmd_t , void *, void **);
-static int pfil_attach(dev_info_t *,  ddi_attach_cmd_t);
-#if SOLARIS2 < 10
-static int pfil_identify(dev_info_t *);
-#endif
-static int pfil_detach(dev_info_t *,  ddi_detach_cmd_t);
-
-#ifdef DDI_DEFINE_STREAM_OPS
-DDI_DEFINE_STREAM_OPS(pfil_devops, nulldev, nulldev, pfil_attach, pfil_detach,
-		      nulldev, pfil_info, D_MP, &pfil_dev_strtab);
-
-#else
-static struct cb_ops pfil_ops = {
-	nodev,		/* cb_open */
-	nodev,		/* cb_close */
-	nodev,		/* cb_strategy */
-	nodev,		/* cb_print */
-	nodev,		/* cb_dump */
-	nodev,		/* cb_read */
-	nodev,		/* cb_write */
-	nodev,		/* cb_ioctl */
-	nodev,		/* cb_devmap */
-	nodev,		/* cb_mmap */
-	nodev,		/* cb_segmap */
-	nochpoll,	/* cb_chpoll */
-	ddi_prop_op,	/* cb_prop_op */
-	&pfilinfo,	/* cb_stream */
-	D_MP		/* cb_flag */
-};
-
-static struct dev_ops pfil_devops = 
-{
-	DEVO_REV,	/* devo_rev */
-	0,		/* devo_refcnt */
-	pfil_info,	/* devo_getinfo */
-#if SOLARIS2 >= 10
-	nulldev,
-#else
-	pfil_identify,	/* devo_identify */
-#endif
-	nulldev,	/* devo_probe */
-	pfil_attach,	/* devo_attach */
-	pfil_detach,	/* devo_detach */
-	nodev,		/* devo_reset */
-	&pfil_ops,	/* devo_cb_ops */
-	NULL		/* devo_bus_ops */
-};
-#endif
-
-static struct modldrv modldrv = {
-	&mod_driverops, "pfil Streams driver "/**/PFIL_RELEASE, &pfil_devops
-};
-
-/************************************************************************
- * STREAMS module information
- */
-static int pfilmodopen(queue_t *, dev_t *, int, int, cred_t *);
-static int pfilmodclose(queue_t *, int, cred_t *);
-
-static struct qinit pfilmod_rinit = {
-	(pfi_t)pfilmodrput, NULL, pfilmodopen, pfilmodclose,
-	NULL, &pfil_minfo, NULL
-};
-
-static struct qinit pfilmod_winit = {
-	(pfi_t)pfilmodwput, NULL, NULL, NULL, NULL, &pfil_minfo, NULL
-};
-
-struct streamtab pfil_mod_strtab = {
-	&pfilmod_rinit, &pfilmod_winit
-};
-
-static struct fmodsw fsw = {
-	"pfil", &pfil_mod_strtab, D_MP
-};
-
-static struct modlstrmod modlstrmod = {
-	&mod_strmodops, "pfil Streams module "/**/PFIL_RELEASE,
-	&fsw
-};
-
-/************************************************************************
- * STREAMS externally visible information for _init() and _info ()
- */
-static struct modlinkage modlinkage = {
-	MODREV_1,
-	{ (void *)&modlstrmod, (void *)&modldrv, NULL }
-};
-
-/************************************************************************
- * STREAMS device functions
- */
-static dev_info_t *pfil_dev_info;
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_attach                                                 */
-/* Returns:     int     - DDI_SUCCESS for success, otherwise DDI_FAILURE    */
-/* Parameters:  devi(I) - pointer to packet information                     */
-/*              cmd(I)  - DDI command to process                            */
-/*                                                                          */
-/* Called when the driver has been attached, just create the device file.   */
-/* ------------------------------------------------------------------------ */
-/*ARGUSED*/
-static int pfil_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
-{
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(3,(CE_CONT, "!pfil_attach(%p,%x)\n", (void *)devi, cmd));
-
-	if (cmd != DDI_ATTACH)
-		return (DDI_FAILURE);
-
-	pfil_dev_info = devi;
-
-#if SOLARIS2 >= 8
-	return (ddi_create_minor_node(devi, "pfil", S_IFCHR, 0, DDI_PSEUDO, 0));
-#else
-	return (ddi_create_minor_node(devi, "pfil", S_IFCHR, 0, NULL, 0));
-#endif
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_detach                                                 */
-/* Returns:     int     - DDI_SUCCESS for success, otherwise DDI_FAILURE    */
-/* Parameters:  devi(I) - pointer to device information                     */
-/*              cmd(I)  - DDI command to process                            */
-/*                                                                          */
-/* Nothing to do here(?) except return that everything is ok.               */
-/* ------------------------------------------------------------------------ */
-/*ARGUSED*/
-static int pfil_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
-{
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(3,(CE_CONT, "!pfil_detach(%p,%x)\n", (void *)devi, cmd));
-
-	if (cmd != DDI_DETACH)
-		return (DDI_FAILURE);
-
-	ASSERT(devi == pfil_dev_info);
-
-	ddi_remove_minor_node(devi, NULL);
-	return (DDI_SUCCESS);
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_info                                                   */
-/* Returns:     int - DDI_SUCCESS (success), DDI_FAILURE (failure)          */
-/* Parameters:  dip(I) - pointer to device information                      */
-/*              cmd(I) - DDI command to process                             */
-/*              arg(I) - paramter to the command to be processed            */
-/*              res(O) - pointer to storage for returning results           */
-/*                                                                          */
-/* Handles information queries made by the kernel of the STREAMS device.    */
-/* ------------------------------------------------------------------------ */
-/*ARGUSED*/
-static int pfil_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
-			 void **res)
-{
-	int result = DDI_FAILURE;
-
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(3,(CE_CONT, "!pfil_info(%p,%x,%p,%p)\n", (void *)dip, infocmd,
-		 arg, (void *)res));
-
-	switch (infocmd)
-	{
-	case DDI_INFO_DEVT2DEVINFO:
-		if (pfil_dev_info != NULL) {
-			*res = (void *)pfil_dev_info;
-			result = DDI_SUCCESS;
-		}
-		break;
-	case DDI_INFO_DEVT2INSTANCE:
-		*res = NULL;
-		result = DDI_SUCCESS;
-		break;
-	default :
-		break;
-	}
-	return result;
-}
-
-
-#if SOLARIS2 < 10
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_identify                                               */
-/* Returns:     int - DDI_IDENTIFIED (success), DDI_NOT_IDENTIFIED (failure)*/
-/* Parameters:  devi(I) -  pointer to a dev_info structure                  */
-/*                                                                          */
-/* Check to see if this module is correctly associated with the device info */
-/* structure passed in.                                                     */
-/* ------------------------------------------------------------------------ */
-static int pfil_identify(dev_info_t *devi)
-{
-	int result = DDI_NOT_IDENTIFIED;
-
-	/*LINTED: E_CONSTANT_CONDITION*/
-	PRINT(3,(CE_CONT, "!pfil_identify(%p)\n", (void *)devi));
-	if (strcmp((char *)ddi_get_name(devi), "!pfil") == 0)
-		result = DDI_IDENTIFIED;
-
-	return result;
-}
-#endif
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfildevopen                                                 */
-/* Returns:     int      - 0 == sucess, else failure                        */
-/* Parameters:  q(I)     - pointer to STREAMS queue                         */
-/*              devp(I)  - pointer to a device number                       */
-/*              oflag(I) - file mode open flags (always 0 for module opens) */
-/*              sflag(I) - flag indicating how the open is being made       */
-/*              crp(I)   - pointer to message credentials from the user     */
-/*                                                                          */
-/* Perform any action required to open the STREAMS device, supporting it    */
-/* being opened in a cloning fashion.                                       */
-/* ------------------------------------------------------------------------ */
-/*ARGSUSED*/
-static int pfildevopen(queue_t *q, dev_t *devp, int oflag, int sflag,
-		       cred_t *crp)
-{
-	int result = 0;
-
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(3,(CE_CONT, "!pfildevopen(%p,%p,%x,%x,%p) [%s]\n",
-		 (void *)q, (void *)devp, oflag, sflag, (void *)crp, QTONM(q)));
-	/*
-	 * As per recommendation on man page open(9e)
-	 */
-	if ((sflag & MODOPEN) != 0)
-		result = ENXIO;
-
-	if (result == 0)
-		qprocson(q);
-
-	return result;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfildevclose                                                */
-/* Returns:     int      - always returns 0.                                */
-/* Parameters:  q(I)     - pointer to STREAMS queue                         */
-/*              flag(I)  - file status flag                                 */
-/*              crp(I)   - pointer to message credentials from the user     */
-/*                                                                          */
-/* Perform any action required to close the STREAMS device.                 */
-/* ------------------------------------------------------------------------ */
-/*ARGSUSED*/
-static int pfildevclose(queue_t *q, int flag, cred_t *crp)
-{
-
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(3,(CE_CONT, "!pfildevclose(%p,%x,%p) [%s]\n",
-		 (void *)q, flag, (void *)crp, QTONM(q)));
-	qprocsoff(q);
-
-#ifdef IRE_ILL_CN
-	if (q == pfildq)
-		pfildq = NULL;
-#endif
-
-	return 0;
-}
-
-/************************************************************************
- * STREAMS module functions
- */
-/* ------------------------------------------------------------------------ */
-/* Function:    pfilmodopen                                                 */
-/* Returns:     int      - 0 == success, else error                         */
-/* Parameters:  q(I)     - pointer to read-side STREAMS queue               */
-/*              devp(I)  - pointer to a device number                       */
-/*              oflag(I) - file status open flags (always 0 for module open)*/
-/*              sflag(I) - flag indicating how the open is being made       */
-/*              crp(I)   - pointer to message credentials from the user     */
-/*                                                                          */
-/* open() entry hook for the STREAMS module.                                */
-/* ------------------------------------------------------------------------ */
-/*ARGSUSED*/
-static int pfilmodopen(queue_t *q, dev_t *devp, int oflag, int sflag,
-		       cred_t *crp)
-{
-
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(3,(CE_CONT, "!pfilmodopen(%p,%p,%x,%x,%p) [%s]\n",
-		 (void *)q, (void *)devp, oflag, sflag, (void *)crp, QTONM(q)));
-
-	/*
-	 * As per recommendation on man page open(9e)
-	 */
-	if (sflag != MODOPEN)
-		return ENXIO;
-
-	q->q_ptr = qif_new(q, KM_SLEEP);
-	WR(q)->q_ptr = q->q_ptr;
-	qprocson(q);
-	return 0;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfilmodclose                                                */
-/* Returns:     int     - always returns 0.                                 */
-/* Parameters:  q(I)    - pointer to read-side STREAMS queue                */
-/*              flag(I) - file status flag                                  */
-/*              crp(I)  - pointer to message credentials from the user      */
-/*                                                                          */
-/* close() entry hook for the STREAMS module. qif_delete() takes care of    */
-/* setting q_ptr back to NULL for both this and the write side queue.       */
-/* ------------------------------------------------------------------------ */
-/*ARGSUSED*/
-static int pfilmodclose(queue_t *q, int flag, cred_t *crp)
-{
-
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(3,(CE_CONT, "!pfilmodclose(%p,%x,%p) [%s]\n",
-		 (void *)q, flag, (void *)crp, QTONM(q)));
-
-	qprocsoff(q);
-
-#ifdef IRE_ILL_CN
-	pfil_remif(q);
-#endif
-	qif_delete(q->q_ptr, q);
-	return 0;
-}
-
-/************************************************************************
- * other support functions
- */
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_precheck                                               */
-/* Returns:     int - < 0 pass packet because it's not a type subject to    */
-/*                    firewall rules (i.e. internal STREAMS messages),      */
-/*                    0 == pass packet, else > 0 indicates passing          */
-/*                    prohibited (possibly due to an error occuring in      */
-/*                    this function.)                                       */
-/* Parameters:  q(I)   - pointer to STREAMS queue                           */
-/*              mp(I)  - pointer to STREAMS message                         */
-/*              qif(I) - pointer to per-queue interface information         */
-/* Locks:       pfil_rw                                                     */
-/*                                                                          */
-/* In here we attempt to determine if there is an IP packet within an mblk  */
-/* that is being passed along and if there is, ensure that it falls on a 32 */
-/* bit aligned address and at least all of the layer 3 header is in one     */
-/* buffer, preferably all the layer 4 too if we recognise it.  Finally, if  */
-/* we can be sure that the buffer passes some sanity checks, pass it on to  */
-/* the registered callbacks for the particular protocol/direction.          */
-/* ------------------------------------------------------------------------ */
-/*ARGSUSED*/
-int pfil_precheck(queue_t *q, mblk_t **mp, int flags, qif_t *qif)
-{
-	register struct ip *ip;
-	size_t hlen, len, off, mlen, iphlen, plen;
-	packet_filter_hook_t *pfh;
-	qpktinfo_t qpkt, *qpi;
-	struct pfil_head *ph;
-	mblk_t *m, *mt = *mp;
-	int err, out, sap;
-	u_char *bp;
-#if SOLARIS2 >= 8
-	ip6_t *ip6;
-#endif
-#ifndef	sparc
-	u_short __ipoff, __iplen;
-#endif
-
-	qpi = &qpkt;
-	qpi->qpi_q = q;
-	qpi->qpi_off = 0;
-	qpi->qpi_name = qif->qf_name;
-	qpi->qpi_real = qif;
-	qpi->qpi_ill = qif->qf_ill;
-	qpi->qpi_hl = qif->qf_hl;
-	qpi->qpi_ppa = qif->qf_ppa;
-	qpi->qpi_num = qif->qf_num;
-	qpi->qpi_flags = qif->qf_flags;
-	qpi->qpi_max_frag = qif->qf_max_frag;
-	if ((flags & PFIL_GROUP) != 0)
-		qpi->qpi_flags |= QF_GROUP;
-
-	/*
-	 * If there is only M_DATA for a packet going out, then any header
-	 * information (which would otherwise appear in an M_PROTO mblk before
-	 * the M_DATA) is prepended before the IP header.  We need to set the
-	 * offset to account for this.
-	 */
-	out = (flags & PFIL_OUT) ? 1 : 0;
-	off = (out) ? qpi->qpi_hl : 0;
-
-	ip = NULL;
-	m = NULL;
-#if SOLARIS2 >= 8
-	ip6 = NULL;
-#endif
-
-	/*
-	 * If the message protocol block indicates that there isn't a data
-	 * block following it, just return back.
-	 */
-	bp = (u_char *)ALIGN32(mt->b_rptr);
-
-	switch (MTYPE(mt))
-	{
-	case M_PROTO :
-	case M_PCPROTO :
-	    {
-		dl_unitdata_ind_t *dl = (dl_unitdata_ind_t *)bp;
-		if ((dl->dl_primitive != DL_UNITDATA_IND) &&
-		    (dl->dl_primitive != DL_UNITDATA_REQ)) {
-			ip = (struct ip *)dl;
-			if ((ip->ip_v == IPVERSION) &&
-			    (ip->ip_hl == (sizeof(*ip) >> 2)) &&
-			    (ntohs(ip->ip_len) == mt->b_wptr - mt->b_rptr)) {
-				off = 0;
-				m = mt;
-			} else {
-				atomic_add_long(&qif->qf_notdata, 1);
-				return -1;
-			}
-		} else {
-			m = mt->b_cont;
-			if (m == NULL) {
-				atomic_add_long(&qif->qf_nodata, 1);
-				return -3;	/* No data blocks */
-			}
-		}
-		break;
-	    }
-	case M_DATA :
-		m = mt;
-		break;
-	default :
-		atomic_add_long(&qif->qf_notdata, 1);
-		return -2;
-	}
-
-	/*
-	 * Find the first data block, count the data blocks in this chain and
-	 * the total amount of data.
-	 */
-	if (ip == NULL)
-		for (m = mt; m && (MTYPE(m) != M_DATA); m = m->b_cont)
-			off = 0;	/* Any non-M_DATA cancels the offset */
-
-	if (m == NULL) {
-		atomic_add_long(&qif->qf_nodata, 1);
-		return -3;	/* No data blocks */
-	}
-
-	/*
-	 * This is a complete kludge to try and work around some bizarre
-	 * packets which drop through into pfil_donotip.
-	 */
-	if ((mt != m) && (MTYPE(mt) == M_PROTO || MTYPE(mt) == M_PCPROTO)) {
-		dl_unitdata_ind_t *dl = (dl_unitdata_ind_t *)bp;
-
-		if ((dl->dl_primitive == DL_UNITDATA_IND) &&
-		    (dl->dl_group_address == 1)) {
-			qpi->qpi_flags |= QF_GROUP;
-			if (((*((u_char *)m->b_rptr) == 0x0) &&
-			    ((*((u_char *)m->b_rptr + 2) == 0x45))))
-				off += 2;
-		}
-
-	}
-
-	/*
-	 * We might have a 1st data block which is really M_PROTO, i.e. it is
-	 * only big enough for the link layer header
-	 */
-	while ((len = m->b_wptr - m->b_rptr) <= off) {
-		off -= len;
-		m = m->b_cont;
-		if (m == NULL) {
-			atomic_add_long(&qif->qf_nodata, 1);
-			return -4;	/* not enough data for IP */
-		}
-	}
-
-	ip = (struct ip *)(m->b_rptr + off);
-	len = m->b_wptr - m->b_rptr - off;
-	mlen = msgdsize(m);
-
-#ifdef IRE_ILL_CN
-	sap = ((s_ill_t *)qif->qf_ill)->ill_sap;
-#else
-	sap = ((ill_t *)qif->qf_ill)->ill_sap;
-#endif
-
-	if (mlen == 0)
-		mlen = m->b_wptr - m->b_rptr;
-	mlen -= off;
-
-#ifdef PFILDEBUG
-	/*LINTED: E_CONSTANT_CONDITION*/
-	PRINT(10,(CE_CONT,
-		  "!IP Filter[%s]: out %d len %ld/%ld sap %d ip %p b_rptr %p off %ld m %p/%d/%d/%p mt %p/%d/%d/%p\n",
-		  qif->qf_name, out, len, mlen, sap,
-		  (void *)ip, (void *)m->b_rptr, off, 
-		  (void *)m, MTYPE(m), (int)MLEN(m), (void *)m->b_cont,
-		  (void *)mt, MTYPE(mt), (int)MLEN(mt), (void *)mt->b_cont));
-#endif
-
-	/*
-	 * If there is more than one copy of this message traversing the
-	 * STREAMS stack (ie the packet is being used for snoop data), the
-	 * IP header isn't on a 32bit aligned address, or the IP header
-	 * isn't contain within a single block, then make a copy which
-	 * meets our requirements and do a freemsg on the one passed in
-	 * since we're no longer using it or passing it up.
-	 */
-
-	if ((pfil_delayed_copy == 0 && m->b_datap->db_ref > 1)
-	    || ((uintptr_t)ip & 0x3) || len < sizeof(*ip)
-	    || (sap != IP_DL_SAP
-#if SOLARIS2 >= 8
-		&& sap != IP6_DL_SAP
-#endif
-	        )) {
-		mblk_t *b;
-		mblk_t *nm;
-		mblk_t *nmt;
-		mblk_t *previous_nm;
-
-forced_copy:
-		nmt = NULL;
-		previous_nm = NULL;
-
-		/*
-		 * Duplicate the message block descriptors up to (and
-		 * including if the offset is non-zero) the block where
-		 * IP begins.
-		 */
-		for (b = mt; b != m || off; b = b->b_cont) {
-			nm = dupb(b);
-			if (nm == NULL) {
-				atomic_add_long(&qif->qf_copyfail, 1);
-				if (nmt)
-					freemsg(nmt);
-				return ENOBUFS;
-			}
-
-			nm->b_cont = NULL;
-			if (nmt)
-				linkb(previous_nm, nm);
-			else
-				nmt = nm;
-			previous_nm = nm;
-
-			/*
-			 * Set the length so the block only contains what
-			 * appears before IP.
-			 */
-			if (b == m) {
-				nm->b_wptr = nm->b_rptr + off;
-				break;
-			}
-		}
-
-		m->b_rptr += off;
-		nm = msgpullup(m, -1);
-		m->b_rptr -= off;
-
-		if (nm == NULL) {
-			atomic_add_long(&qif->qf_copyfail, 1);
-			if (nmt)
-				freemsg(nmt);
-			return ENOBUFS;
-		}
-
-		if (nmt)
-			linkb(previous_nm, nm);
-		else
-			nmt = nm;
-
-		freemsg(mt);
-
-		*mp = nmt;
-		mt = nmt;
-		m = nm;
-
-		ip = (struct ip *)m->b_rptr;
-		len = m->b_wptr - m->b_rptr;
-		mlen = len;
-		off = 0;
-	}
-
-	if (sap == IP_DL_SAP) {
-		u_short tlen;
-
-		hlen = sizeof(*ip);
-
-		/* XXX - might not be aligned (from ppp?) */
-		((char *)&tlen)[0] = ((char *)&ip->ip_len)[0];
-		((char *)&tlen)[1] = ((char *)&ip->ip_len)[1];
-		plen = ntohs(tlen);
-
-		ph = &pfh_inet4;
-	}
-#if SOLARIS2 >= 8
-	else if (sap == IP6_DL_SAP) {
-		u_short tlen;
-
-		hlen = sizeof(ip6_t);
-		ip6 = (ip6_t *)ip;
-
-		/* XXX - might not be aligned (from ppp?) */
-		((char *)&tlen)[0] = ((char *)&ip6->ip6_plen)[0];
-		((char *)&tlen)[1] = ((char *)&ip6->ip6_plen)[1];
-		plen = ntohs(tlen);
-		if (plen == 0)
-			return EMSGSIZE;	/* Jumbo gram */
-
-		ph = &pfh_inet6;
-	}
-#endif 
-	else {
-		sap = -1;
-	}
-
-	if (((sap == IP_DL_SAP) && (ip->ip_v != IPVERSION))
-#if SOLARIS2 >= 8
-	    || ((sap == IP6_DL_SAP) && (((ip6->ip6_vfc) & 0xf0) != 0x60))
-#endif
-	    || sap == -1
-	   ) {
-		atomic_add_long(&qif->qf_notip, 1);
-#ifdef PFILDEBUG
-		pfil_donotip(out, qif, q, m, mt, ip, off);
-#endif
-		return EINVAL;
-	}
-
-	if (sap == IP_DL_SAP)
-		iphlen = ip->ip_hl << 2;
-#if SOLARIS2 >= 8
-	else if (sap == IP6_DL_SAP)
-		iphlen = sizeof(ip6_t);
-#endif
-
-	if ((
-#if SOLARIS2 >= 8
-	     (sap == IP6_DL_SAP) && (mlen < plen)) ||
-	    ((sap == IP_DL_SAP) &&
-#endif 
-	     ((iphlen < hlen) || (iphlen > plen) || (mlen < plen)))) {
-		/*
-		 * Bad IP packet or not enough data/data length mismatches
-		 */
-		atomic_add_long(&qif->qf_bad, 1);
-		return EINVAL;
-	}
-
-	/*
-	 * If we don't have enough data in the mblk or we haven't yet copied
-	 * enough (above), then copy some more.
-	 */
-	if ((iphlen > len)) {
-		if (m->b_datap->db_ref > 1)
-			goto forced_copy;
-		if (!pullupmsg(m, (int)iphlen + off)) {
-			atomic_add_long(&qif->qf_nodata, 1);
-			return ENOBUFS;
-		}
-		ip = (struct ip *)ALIGN32(m->b_rptr + off);
-	}
-
-	/*
-	 * Discard any excess data.
-	 */
-	if (sap == IP6_DL_SAP && len > iphlen + plen)
-		m->b_wptr = m->b_rptr + off + plen + iphlen;
-	else if (sap == IP_DL_SAP && len > plen)
-		m->b_wptr = m->b_rptr + off + plen;
-
-	/*
-	 * The code in IPFilter assumes that both the ip_off and ip_len
-	 * fields are in host byte order, so convert them here to fulfill
-	 * that expectation.
-	 *
-	 * If the target compile host is non-SPARC, assume it is a little
-	 * endian machine, requiring the conversion of offset/length fields
-	 * to both be host byte ordered.
-	 */
-#ifndef sparc
-	if (sap == IP_DL_SAP) {
-		__ipoff = (u_short)ip->ip_off;
-		ip->ip_len = plen;
-		ip->ip_off = ntohs(__ipoff);
-	}
-#endif
-
-	qpi->qpi_m = m;
-	qpi->qpi_off = off;
-	qpi->qpi_data = ip;
-
-	if (qif->qf_ipmp != NULL)
-		qif = qif->qf_ipmp;
-
-	READ_ENTER(&ph->ph_lock);
-
-	pfh = pfil_hook_get(flags & PFIL_INOUT, ph);
-	err = 0;
-
-	/*LINTED: E_CONSTANT_CONDITION*/
-	PRINT(8,(CE_CONT, "!pfil_hook_get(%x,%p) = %p\n",
-		 flags, (void *)ph, (void *)pfh));
-	for (; pfh; pfh = pfh->pfil_next)
-		if (pfh->pfil_func) {
-			err = (*pfh->pfil_func)(ip, iphlen, qif, out, qpi, mp);
-			if (err || !*mp)
-				break;
-			/*
-			 * fr_pullup may have allocated a new buffer.
-			 */
-			ip = qpi->qpi_data;
-		}
-	RW_EXIT(&ph->ph_lock);
-
-	/*
-	 * Functions called via pfil_func should only return values >= 0, so
-	 * convert any that are < 0 to be > 0 and preserve the absolute value.
-	 */
-	if (err < 0)
-		err = -err;
-
-	/*
-	 * If we still have a STREAMS message after calling the filtering
-	 * hooks, return the byte order of the fields changed above on
-	 * platforms where this is required.  They are refetched from the
-	 * packet headers because the callback (pfil_func) may have changed
-	 * them in some way.
-	 */
-#ifndef sparc
-	if ((err == 0) && (*mp != NULL)) {
-		if (sap == IP_DL_SAP) {
-			__iplen = (u_short)ip->ip_len;
-			__ipoff = (u_short)ip->ip_off;
-			ip->ip_len = htons(__iplen);
-			ip->ip_off = htons(__ipoff);
-		}
-	}
-#endif
-	return err;
-}
-
-
-/************************************************************************
- * kernel module initialization
- */
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    _init                                                       */
-/* Returns:     int - DDI_SUCCESS == success, else failure                  */
-/* Parameters:  Nil.                                                        */
-/*                                                                          */
-/* Initialise the kernel module and if that succeeds, call other init       */
-/* routines, elsewhere, that handle initialisation of the more generic      */
-/* components.                                                              */
-/* ------------------------------------------------------------------------ */
-int _init(void)
-{
-	int result;
-
-	result = pfil_nd_init();
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(2,(CE_CONT, "pfil_nd_init():%d\n", result));
-	if (result != 0)
-		return DDI_FAILURE;
-
-	if (qif_startup() == -1)
-		return DDI_FAILURE;
-
-	rw_init(&pfil_rw, "pfil_rw", RW_DRIVER, 0);
-#ifdef IRE_ILL_CN
-	mutex_init(&s_ill_g_head_lock, NULL, MUTEX_DRIVER, NULL);
-#endif
-	pfil_startup();
-
-	result = mod_install(&modlinkage);
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(1,(CE_CONT, "_init():%d\n", result));
-
-	return result;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    _fini                                                       */
-/* Returns:     int - DDI_SUCCESS == success, else failure                  */
-/* Parameters:  Nil.                                                        */
-/*                                                                          */
-/* Called when the OS attempts to unload the module, it should only be      */
-/* allowed to succeed if pfil is not currently in the middle of any STREAMS */
-/* "connections".  If it isn't then turn ourselves off and remove the module*/
-/* ------------------------------------------------------------------------ */
-int _fini(void)
-{
-	int result;
-
-	if (qif_head != NULL)
-		return EBUSY;
-	result = mod_remove(&modlinkage);
-
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(1,(CE_CONT, "_fini():%d\n", result));
-
-	if (result == DDI_SUCCESS) {
-		pfil_nd_fini();
-		qif_stop();
-#ifdef IRE_ILL_CN
-		mutex_destroy(&s_ill_g_head_lock);
-#endif
-		pfil_installed = 0;
-	}
-	return result;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    _info                                                       */
-/* Returns:     int - DDI_SUCCESS == success, else failure                  */
-/* Parameters:  modinfop(I) - pointer to module informatio buffer           */
-/*                                                                          */
-/* Standard _info() implementation that just calls mod_info on its linkage  */
-/* structure so information can be copied back into the modinfop struct.    */
-/* ------------------------------------------------------------------------ */
-int _info(struct modinfo *modinfop)
-{
-	int result;
-
-	result = mod_info(&modlinkage, modinfop);
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(3,(CE_CONT, "_info(%p):%x\n", (void *)modinfop, result));
-	return result;
-}
-
-
-/************************************************************************
- * Sun Solaris ON build specific routines follow here.
- */
-#ifdef IRE_ILL_CN
-static void _dump_s_ill(s_ill_t *ts)
-{
-	cmn_err(CE_NOTE, "s_ill next = 0x%p", (void *)ts->ill_next);
-	cmn_err(CE_NOTE, "s_ill sap = 0x%x", ts->ill_sap);
-	cmn_err(CE_NOTE, "s_ill name = %s", ts->ill_name);
-	cmn_err(CE_NOTE, "s_ill rq = 0x%p", (void *)ts->ill_rq);
-}
-
-static void
-_dump_s_ill_all(void)
-{
-	s_ill_t *ill;
-	/* who care locks */
-	if (pfildebug > 10) {
-		cmn_err(CE_NOTE, "s_ill_g_head = 0x%p\n", (void *)s_ill_g_head);
-		for (ill = s_ill_g_head; ill; ill = ill->ill_next) {
-			_dump_s_ill(ill);
-		}
-		cmn_err(CE_NOTE, "s_ill_g_head done\n");
-	}
-}
-
-
-/*
- * Allocate an s_ill_t for this interface (name) if needed.
- * Populate the read queue pointer.
- */
-void pfil_addif(queue_t *rq, const char *name, int sap)
-{
-	s_ill_t *ill;
-
-	mutex_enter(&s_ill_g_head_lock);
-
-	/* XXX: Need to check for duplicate */
-	/* If replumbed, rq will be updated */
-	for (ill = s_ill_g_head; ill; ill = ill->ill_next) {
-
-		if (ill->ill_sap == sap &&
-		    strncmp(name, ill->ill_name, LIFNAMSIZ) == 0) {
-		  /* interface already there */
-			break;
-		}
-	}
-
-	if (!ill) {
-		ill = kmem_zalloc(sizeof(s_ill_t), KM_NOSLEEP);
-		if (!ill) {
-			cmn_err(CE_NOTE, "PFIL: malloc(%d) for ill failed",
-			(int)sizeof(s_ill_t));
-			mutex_exit(&s_ill_g_head_lock);
-			return;
-		}
-		ill->ill_sap = sap;
-		(void) strncpy(ill->ill_name, name, LIFNAMSIZ);
-		ill->ill_name[sizeof(ill->ill_name) - 1] = '\0';
-		ill->ill_next = s_ill_g_head;
-		s_ill_g_head = ill;
-	}
-
-	ASSERT(ill != NULL);
-	ill->ill_rq = rq;
-	_dump_s_ill_all();
-	mutex_exit(&s_ill_g_head_lock);
-}
-
-
-/*
- * Deactivate any s_ill_t for this interface (queue pair).
- * Called when a module is being closed (popped).
- */
-static void pfil_remif(queue_t *rq)
-{
-	s_ill_t *ill;
-
-	WRITE_ENTER(&pfil_rw);
-	mutex_enter(&s_ill_g_head_lock);
-
-	for (ill = s_ill_g_head; ill; ill = ill->ill_next)
-		if (ill->ill_rq == rq)
-			ill->ill_rq = 0;
-	_dump_s_ill_all();
-	mutex_exit(&s_ill_g_head_lock);
-	RW_EXIT(&pfil_rw);
-}
-#endif /* IRE_ILL_CN */
-
-
-/************************************************************************
- *
- */
-#ifdef PFILDEBUG
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_donotip                                                */
-/* Returns:     Nil                                                         */
-/* Parameters:  out(I) - in(0)/out(1) flag for direction of message         */
-/*              qif(I) - pointer to per-queue interface information         */
-/*              q(I)   - pointer to STREAMS queue                           */
-/*              m(I)   - pointer to STREAMS message block where IP starts   */
-/*              mt(I)  - pointer to the start of the STREAMS message        */
-/*              ip(I)  - pointer to the start of the IP header              */
-/*              off(I) - offset from start of message to start of IP header */
-/*                                                                          */
-/* This function is here solely for dumping out the contents of an mblk and */
-/* showing what related information is known about it, to aid in debugging  */
-/* processing of messages going by that fail to be recognised properly.     */
-/* ------------------------------------------------------------------------ */
-void pfil_donotip(int out, qif_t *qif, queue_t *q, mblk_t *m, mblk_t *mt, struct ip *ip, size_t off)
-{
-	u_char *s, outb[256], *t;
-	int i;
-
-	outb[0] = '\0';
-	outb[1] = '\0';
-	outb[2] = '\0';
-	outb[3] = '\0';
-	s = ip ? (u_char *)ip : outb;
-	if (!ip && (m == mt) && m->b_cont && (MTYPE(m) != M_DATA))
-		m = m->b_cont;
-
-	/*LINTED: E_CONSTANT_CONDITION*/
-	PRINT(9,(CE_CONT, 
-		 "!IP %s:%d %ld %p %p %p ip %p b_rptr %p off %ld m %p/%d/%d/%p mt %p/%d/%d/%p\n",
-		  qif ? qif->qf_name : "?", out, qif ? qif->qf_hl : -1, 
-		  (void *)q, q ? q->q_ptr : NULL, q ? (void *)q->q_qinfo : NULL,
-		  (void *)ip, (void *)m->b_rptr, off, 
-		  (void *)m, MTYPE(m), (int)MLEN(m), (void *)m->b_cont,
-		  (void *)mt, MTYPE(mt), (int)MLEN(mt), (void *)mt->b_cont));
-	/*LINTED: E_CONSTANT_CONDITION*/
-	PRINT(9,(CE_CONT, "%02x%02x%02x%02x\n", *s, *(s+1), *(s+2), *(s+3)));
-	while (m != mt) {
-		i = 0;
-		t = outb;
-
-		s = mt->b_rptr;
-		(void)sprintf((char *)t, "%d:", MTYPE(mt));
-		t += strlen((char *)t);
-		for (; (i < 100) && (s < mt->b_wptr); i++) {
-			(void)sprintf((char *)t, "%02x%s", *s++,
-				((i & 3) == 3) ? " " : "");
-			t += ((i & 3) == 3) ? 3 : 2;
-		}
-		*t++ = '\n';
-		*t = '\0';
-		/*LINTED: E_CONSTANT_CONDITION*/
-		PRINT(50,(CE_CONT, "%s", outb));
-		mt = mt->b_cont;
-	}
-	i = 0;
-	t = outb;
-	s = m->b_rptr;
-	(void)sprintf((char *)t, "%d:", MTYPE(m));
-	t += strlen((char *)t);
-	for (; (i < 100) && (s < m->b_wptr); i++) {
-		(void)sprintf((char *)t, "%02x%s", *s++,
-			      ((i & 3) == 3) ? " " : "");
-		t += ((i & 3) == 3) ? 3 : 2;
-	}
-	*t++ = '\n';
-	*t = '\0';
-	/*LINTED: E_CONSTANT_CONDITION*/
-	PRINT(50,(CE_CONT, "%s", outb));
-}
-#endif
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_property_update                                        */
-/* Returns:     int - DDI_SUCCESS == success, else failure                  */
-/* Parameters:  modinfop(I) - pointer to module informatio buffer           */
-/*                                                                          */
-/* Fetch configuration file values that have been entered into the          */
-/* pfil.conf driver file.                                                   */
-/* ------------------------------------------------------------------------ */
-static int pfil_property_update(dev_info_t *dip)
-{
-	char *list, *s, *t;
-	int err;
-
-	if (ddi_prop_update_int(DDI_DEV_T_ANY, dip,
-				"ddi-no-autodetach", 1) == -1) {
-		cmn_err(CE_WARN, "!updating ddi-no-authdetach failed");
-		return DDI_FAILURE;
-	}
-
-	list = NULL;
-	err = ddi_prop_lookup_string(DDI_DEV_T_ANY, dip,
-				     0, "qif_ipmp_set", &list);
-#ifdef	IPFDEBUG
-	cmn_err(CE_CONT, "IP Filter: lookup_string(pfil_ipmp_list) = %d\n",
-		err);
-#endif
-	if (err == DDI_SUCCESS) {
-		t = NULL;
-		s = list;
-		do {
-			if (t != NULL)
-				s = t + 1;
-			t = strchr(s, ';');
-			if (t != NULL)
-				*t = '\0';
-			qif_ipmp_update(s);
-		} while (t != NULL);
-
-		ddi_prop_free(list);
-	}
-
-	return DDI_SUCCESS;
-}
-
-
-#if SOLARIS2 == 8
-int miocpullup(mblk_t *m, size_t len)
-{
-	if (m->b_cont == NULL)
-		return 0;
-	return pullupmsg(m->b_cont, len);
-}
-#endif
--- a/usr/src/uts/common/inet/pfil/pfilstream.c	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,761 +0,0 @@
-/*
- * Copyright (C) 2000, 2003 by Darren Reed.
- *
- * See the IPFILTER.LICENCE file for details on licencing.
- *
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-struct uio;
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/errno.h>
-#include <sys/stream.h>
-#ifdef HPUX_1111
-# include <sys/cred.h>
-#endif
-#include <sys/dlpi.h>
-#include <sys/cmn_err.h>
-#ifdef sun
-# include <sys/atomic.h>
-# include <sys/sockio.h>
-# include <sys/ksynch.h>
-# include <sys/strsubr.h>
-# include <sys/strsun.h>
-#endif
-#ifdef __hpux
-# include <sys/dlpi_ext.h>
-# include <net/mtcp.h>
-#endif
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <net/if.h>
-#include <netinet/if_ether.h>
-#ifdef sun
-# include <inet/common.h>
-# if SOLARIS2 >= 8
-#  include <netinet/ip6.h>
-# else
-#  include <net/if_dl.h>
-# endif
-# if SOLARIS2 >= 10
-#  include <sys/policy.h>
-# endif
-# undef IPOPT_EOL
-# undef IPOPT_NOP
-# undef IPOPT_LSRR
-# undef IPOPT_SSRR
-# undef IPOPT_RR
-# include <inet/ip.h>
-# include <inet/ip_if.h>
-#endif
-
-#include "compat.h"
-#include "qif.h"
-#include "pfil.h"
-#include "pfild.h"
-
-#if SOLARIS2 >= 10
-extern queue_t *pfildq;
-#endif
-
-#undef	IEEESAP_SNAP
-#define	IEEESAP_SNAP		0xAA	/* SNAP SAP */
-
-#ifdef	PFILDEBUG
-# define	PRINT(l,x)	do {if ((l) <= pfildebug) cmn_err x; } while (0)
-# define	QTONM(x)	(((x) && (x)->q_ptr) ? \
-				 ((qif_t *)(x)->q_ptr)->qf_name : "??")
-#else
-# define	PRINT(l,x)	;
-#endif
-
-#ifndef	IP_DL_SAP
-# define	IP_DL_SAP	0x800
-#endif
-
-#define	AFtoSAP(af)	(((af) == AF_INET6) ? IP6_DL_SAP : IP_DL_SAP)
-
-static	int	pfil_drv_priv __P((cred_t *));
-
-
-#ifdef  PFILDEBUG
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_printmchain                                            */
-/* Returns:     void                                                        */
-/* Parameters:  mp(I) - pointer to mblk message                             */
-/*                                                                          */
-/* This is primarly for debugging purposes - print out the contents of a    */
-/* STREAMS mblk message, just by data block type or also contents (in hex)  */
-/* if the value of pfil_debug has been turned up enough.                    */
-/* ------------------------------------------------------------------------ */
-void pfil_printmchain(mblk_t *mp)
-{
-	char buf[80], cbuf[17], *t;
-	u_char c, *s, *r;
-	mblk_t *mc;
-	int i;
-
-	for (mc = mp; mc; mc = mc->b_cont) {
-		i = mc->b_wptr - mc->b_rptr;
-		/*LINTED: E_CONSTANT_CONDITION*/
-		PRINT(50,(CE_CONT, "m(%p):%d len %d cont %p\n",
-			(void *)mc, MTYPE(mc), i, (void *)mc->b_cont));
-		s = (u_char *)mc->b_rptr;
-		r = (u_char *)cbuf;
-		for (i = 0, t = buf; s < mc->b_wptr; ) {
-			c = *s++;
-			if (c >= 0x20  && c < 0x7f)
-				*r++ = c;
-			else
-				*r++ = '.';
-			*r = '\0';
-#ifdef	__hpux
-			sprintf(t, 4, "%02x", c);
-#else
-			(void)sprintf(t, "%02x", c);
-#endif
-			t += 2;
-			i++;
-			if ((i & 15) == 0) {
-				/*LINTED: E_CONSTANT_CONDITION*/
-				PRINT(99,(CE_CONT, "%03d:%s %s\n", i - 16,
-					buf, cbuf));
-				t = buf;
-				r = (u_char *)cbuf;
-			} else if ((i & 3) == 0)
-				*t++ = ' ';
-		}
-		if (t > buf) {
-			/*LINTED: E_CONSTANT_CONDITION*/
-			PRINT(99,(CE_CONT, "%03d:%s %s\n", i - (i & 15), buf,
-				cbuf));
-		}
-	}
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_printioctl                                             */
-/* Returns:     void                                                        */
-/* Parameters:  mp(I) - pointer to mblk message with ioctl                  */
-/*                                                                          */
-/* This is primarly for debugging purposes - print out in a more legible    */
-/* format what an ioctl is.                                                 */
-/* ------------------------------------------------------------------------ */
-static void pfil_printioctl(mblk_t *mp)
-{
-	struct iocblk *iocp;
-	int cmd, num;
-	char buf[80], l;
-
-	if (!mp || !mp->b_datap || !mp->b_datap->db_base)
-		return;
-	iocp = (struct iocblk *)mp->b_rptr;
-	cmd = iocp->ioc_cmd;
-
-#ifdef __hpux
-	sprintf(buf, sizeof(buf), "0x%x=_IO", cmd);
-#else
-	(void)sprintf(buf, "0x%x=_IO", cmd);
-#endif
-	switch (cmd >> 24)
-	{
-	case 0x20:
-		(void)strcat(buf, "V(");
-		break;
-	case 0x40:
-		(void)strcat(buf, "R(");
-		break;
-	case 0x80:
-		(void)strcat(buf, "W(");
-		break;
-	case 0xc0:
-		(void)strcat(buf, "WR(");
-		break;
-	default :
-#ifdef __hpux
-		sprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
-			"0x%x(", cmd >> 24);
-#else
-		(void)sprintf(buf + strlen(buf), "0x%x(", cmd >> 24);
-#endif
-		break;
-	}
-
-	cmd &= 0x00ffffff;
-	num = cmd & 0xff;
-	l = (cmd >> 8) & 0xff;
-#ifdef	__hpux
-	sprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
-		"%c,%d,%d)", l, num, (cmd >> 16) & 0xff);
-#else
-	(void)sprintf(buf + strlen(buf), "%c,%d,%d)",
-		l, num, (cmd >> 16) & 0xff);
-#endif
-	/*LINTED: E_CONSTANT_CONDITION*/
-	PRINT(3,(CE_CONT,
-		 "!pfil_printioctl: %s (%d) cr %p id %d flag 0x%x count %ld error %d rval %d\n",
-		 buf, (int)sizeof(*iocp), (void *)iocp->ioc_cr, iocp->ioc_id,
-		 iocp->ioc_flag, iocp->ioc_count, iocp->ioc_error,
-		 iocp->ioc_rval));
-	pfil_printmchain(mp);
-}
-#endif	/* PFILDEBUG */
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfilbind                                                    */
-/* Returns:     int  - 0 == success, else error                             */
-/* Parameters:  q(I) - pointer to queue                                     */
-/*                                                                          */
-/* Check to see if a queue (or the otherside of it) is missing a qif_t      */
-/* structure.  If neither have one then allocate a new one, else copy the   */
-/* q_ptr from one to the other.                                             */
-/* ------------------------------------------------------------------------ */
-int pfilbind(queue_t *q)
-{
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(3,(CE_CONT, "!pfilbind(%p) ptr %p O %p\n",
-		 (void *)q, (void *)q->q_ptr, (void *)OTHERQ(q)));
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(3,(CE_CONT, "!R %p %p W %p %p\n",
-		 (void *)RD(q), (void *)RD(q)->q_ptr,
-		 (void *)WR(q), (void *)WR(q)->q_ptr));
-
-	return qif_attach(q);
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfilwput_ioctl                                              */
-/* Returns:     void                                                        */
-/* Parameters:  q(I)  - pointer to queue                                    */
-/*              mp(I) - pointer to STREAMS message                          */
-/*                                                                          */
-/* Handles ioctls for both the STREAMS module and driver.                   */
-/* ------------------------------------------------------------------------ */
-void pfilwput_ioctl(queue_t *q, mblk_t *mp)
-{
-	struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
-	qif_t *qif;
-
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(3,(CE_CONT,
-		 "!pfilwput_ioctl(%p,%p) ioctl(%x,%d,%x,%ld,%d,%d) [%s]\n",
-		 (void *)q, (void *)mp, iocp->ioc_cmd, iocp->ioc_id,
-		 iocp->ioc_flag, iocp->ioc_count, iocp->ioc_rval,
-		 iocp->ioc_error, QTONM(q)));
-#ifdef	PFILDEBUG
-	pfil_printioctl(mp);
-#endif
-
-	if (iocp->ioc_cr && pfil_drv_priv(iocp->ioc_cr) != 0 ) {
-		putnext(q, mp);
-		return;
-	}
-
-	switch (iocp->ioc_cmd)
-	{
-	case DL_IOC_HDR_INFO :
-		qif = q->q_ptr;
-
-		/*
-		 * Fastpath information ioctl.  Update the expected size for
-		 * headers on this queue using to match that in this message.
-		 * Whilst this may not be an IOCACK with the header attached,
-		 * it can also be an indication that something has changed so
-		 * doing an update may not be a bad idea.
-		 * If fastpath headers ever have variable length, this will
-		 * not work.
-		 */
-		WRITE_ENTER(&pfil_rw);
-		qif_update(qif, mp);
-		RW_EXIT(&pfil_rw);
-		if (qif->qf_ill != NULL) {
-			packet_filter_hook_t *pfh;
-
-			READ_ENTER(&pfh_sync.ph_lock);
-			pfh = pfil_hook_get(PFIL_IN, &pfh_sync);
-			for (; pfh; pfh = pfh->pfil_next)
-				if (pfh->pfil_func)
-					(void) (*pfh->pfil_func)(NULL, 0,
-								 qif->qf_ill,
-								 0, qif, NULL);
-			RW_EXIT(&pfh_sync.ph_lock);
-		}
-		break;
-
-#if SOLARIS2 >= 10
-#ifdef SIOCSLIFNAME
-	case SIOCSLIFNAME :
-		if (miocpullup(mp, sizeof(struct lifreq)) == 0) {
-			struct lifreq *lifr;
-			int sap;
-
-			lifr = (struct lifreq *)mp->b_cont->b_rptr;
-# ifdef ILLF_IPV6
-			sap = (lifr->lifr_flags & ILLF_IPV6) ? IP6_DL_SAP :
-							       IP_DL_SAP;
-# else
-			sap = IP_DL_SAP;
-# endif
-			pfil_addif(RD(q), lifr->lifr_name, sap);
-			miocack(q, mp, 0, 0);
-			return;
-		}
-		break;
-#endif
-#else /* pre-S10 */
-#ifdef	SIOCGTUNPARAM
-	case SIOCGTUNPARAM :
-		qif_attach(q);
-		break;
-#endif
-#endif /* pre-S10 */
-#ifdef __hpux
-	case ND_SET :
-	case ND_GET :
-		if (pfil_ioctl_nd(q, mp)) {
-			if (iocp->ioc_error)
-				iocp->ioc_count = 0;
-			mp->b_datap->db_type = M_IOCACK;
-			qreply(q, mp);
-		} else {
-			miocnak(q, mp, 0, EINVAL);
-		}
-		return;
-		break;
-#endif
-	default :
-		break;
-	}
-
-	putnext(q, mp);
-	return;
-}
-
-
-#if SOLARIS2 >= 10
-/*
- * Update interface configuration data from pfild message.
- */
-static void 
-pfil_update_ifaddrs(mblk_t *mp)
-{
-	s_ill_t *ill;
-	int i;
-	struct pfil_ifaddrs *ifaddrslist = (struct pfil_ifaddrs *)mp->b_rptr;
-	int numifs;
-
-	if (MLEN(mp) < sizeof(struct pfil_ifaddrs))
-		return;
-
-	numifs = MLEN(mp) / sizeof (struct pfil_ifaddrs);
-	mutex_enter(&s_ill_g_head_lock);
-
-	for (i = 0; i < numifs; i++) {
-		int sap = AFtoSAP(ifaddrslist[i].localaddr.in.sin_family);
-
-		/* LINTED: E_CONSTANT_CONDITION */
-		PRINT(3,(CE_CONT,"ifs# %d sin_family %d sap %x\n", i,
-			 ifaddrslist[i].localaddr.in.sin_family, sap)); 
-
-		for (ill = s_ill_g_head; ill; ill = ill->ill_next) {
-			if (strncmp(ifaddrslist[i].name, ill->ill_name,
-				    LIFNAMSIZ) == 0 &&
-			    sap == ill->ill_sap) {
-				bcopy(&ifaddrslist[i].localaddr,
-				      &ill->localaddr,
-				      sizeof (ifaddrslist[i].localaddr));
-				bcopy(&ifaddrslist[i].netmask, &ill->netmask,
-				      sizeof (ifaddrslist[i].netmask));
-				bcopy(&ifaddrslist[i].broadaddr,
-				      &ill->broadaddr,
-				      sizeof (ifaddrslist[i].broadaddr));
-				bcopy(&ifaddrslist[i].dstaddr, &ill->dstaddr,
-				      sizeof (ifaddrslist[i].dstaddr));
-				ill->mtu = ifaddrslist[i].mtu;
-			}
-		}
-	}
-
-	mutex_exit(&s_ill_g_head_lock);
-}
-
-
-/*
- * Update valid address set data from pfild message.
- */
-static void pfil_update_ifaddrset(mblk_t *mp)
-{
-	struct pfil_ifaddrset *ifaddrset = (struct pfil_ifaddrset *)mp->b_rptr;
-	int sap;
-	qif_t *qp;
-
-	if (MLEN(mp) < sizeof(struct pfil_ifaddrset))
-		return;
-
-	sap = AFtoSAP(ifaddrset->af);
-
-	READ_ENTER(&pfil_rw);
-
-	qp = qif_iflookup(ifaddrset->name, sap);
-	if (qp != NULL) {
-		if (qp->qf_addrset != NULL)
-			freeb(qp->qf_addrset);
-		qp->qf_addrset = dupb(mp);
-	}
-
-	RW_EXIT(&pfil_rw);
-}
-#endif /* SOLARIS2 >= 10 */
-
-
-/************************************************************************
- * STREAMS device functions
- */
-/* ------------------------------------------------------------------------ */
-/* Function:    pfilwput                                                    */
-/* Returns:     void                                                        */
-/* Parameters:  q(I)  - pointer to queue                                    */
-/*              mp(I) - pointer to STREAMS message                          */
-/*                                                                          */
-/* This is only called for interaction with pfil itself, as the driver      */
-/* /dev/pfil, not the STREAMS module pushed on another queue.  As it does   */
-/* not do any IO, this should never be called except to handle ioctl's and  */
-/* so all other messages are free'd and no reply sent back.                 */
-/* The only ioctls handled by the driver are ND_GET/ND_SET.                 */
-/* pfilwput also handles PFILCMD_IFADDRS and PFILCMD_IFADDRSET messages.    */
-/* NOTE: HP-UX does not need or have pfil implemented as a STREAMS device.  */
-/* ------------------------------------------------------------------------ */
-#ifdef sun
-void pfilwput(queue_t *q, mblk_t *mp)
-{
-	struct iocblk *iocp;
-	uint32_t cmd;
-
-# ifdef PFILDEBUG
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(9,(CE_CONT, "!pfilwput(%p,%p) [%s] qif %p\n",
-		 (void *)q, (void *)mp, QTONM(q), (void *)q->q_ptr));
-# endif
-
-	switch (MTYPE(mp))
-	{
-#if SOLARIS2 >= 10
-	case M_PROTO:
-		/*
-		 * Is it a valid PFILCMD message?
-		 */
-		if (MLEN(mp) < sizeof(uint32_t) || (mp->b_cont == NULL)) {
-			/*LINTED: E_CONSTANT_CONDITION*/
-			PRINT(10, (CE_NOTE, "invalid PFILCMD"));
-			break;
-		}
-
-		/*
-		 * It's a message from pfild.  Remember pfild's read queue for
-		 * later use when sending packets; then process this message.
-		 */
-		pfildq = RD(q);
-		cmd = *((uint32_t *)mp->b_rptr);
-		switch (cmd) {
-		case PFILCMD_IFADDRS:
-			pfil_update_ifaddrs(mp->b_cont);
-			break;
-		case PFILCMD_IFADDRSET:
-			pfil_update_ifaddrset(mp->b_cont);
-			break;
-		default:
-			break;
-		}
-		break;
-#endif
-	case M_IOCTL:
-		iocp = (struct iocblk *)mp->b_rptr;
-		switch (iocp->ioc_cmd)
-		{
-		case ND_SET :
-		case ND_GET :
-			if (pfil_ioctl_nd(q, mp)) {
-				if (iocp->ioc_error)
-					iocp->ioc_count = 0;
-				mp->b_datap->db_type = M_IOCACK;
-				qreply(q, mp);
-			} else {
-				miocnak(q, mp, 0, EINVAL);
-			}
-			break;
-
-		default :
-			miocnak(q, mp, 0, EINVAL);
-			break;
-		}
-		return;
-
-	default :
-		break;
-	}
-
-	freemsg(mp);
-}
-#endif
-
-
-/************************************************************************
- * STREAMS module functions
- */
-/* ------------------------------------------------------------------------ */
-/* Function:    pfilmodwput                                                 */
-/* Returns:     void                                                        */
-/* Parameters:  q(I)  - pointer to queue                                    */
-/*              mp(I) - pointer to STREAMS message                          */
-/*                                                                          */
-/* This function is called as part of the STREAMS module message processing */
-/* for messages going down to the device drivers.                           */
-/* ------------------------------------------------------------------------ */
-void pfilmodwput(queue_t *q, mblk_t *mp)
-{
-	union DL_primitives *dl;
-	qif_t *qif;
-
-	qif = q->q_ptr;
-
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(9,(CE_CONT, "!pfilmodwput(%p,%p) T:%d [%s,%s] qif %p %p\n",
-		 (void *)q, (void *)mp, MTYPE(mp), QTONM(q), QTONM(OTHERQ(q)),
-		 (void *)qif, (void *)qif->qf_ill));
-
-	switch (MTYPE(mp))
-	{
-	case M_PROTO :
-	case M_PCPROTO :
-		dl = (union DL_primitives *)mp->b_rptr;
-
-		/* LINTED: E_CONSTANT_CONDITION */
-		PRINT(7,(CE_CONT, "!pfilmodwput: %p dl_primitive:%d\n",
-			 (void *)mp, dl->dl_primitive));
-
-		if ((MLEN(mp) < sizeof(dl_unitdata_req_t)) ||
-		    (dl->dl_primitive != DL_UNITDATA_REQ)) {
-			break;
-		}
-
-		/*FALLTHROUGH*/
-	case M_DATA :
-		atomic_add_long(&qif->qf_nw, 1);
-
-		if (qif->qf_ill != NULL) {
-			int i;
-
-			i = pfil_precheck(q, &mp, PFIL_OUT, qif);
-
-			/* LINTED: E_CONSTANT_CONDITION */
-			PRINT(9, (CE_CONT, "!%s: pfil_precheck=%d mp %p\n",
-				  "pfilmodwput", i, (void *)mp));
-			if (mp == NULL)
-				return;
-			else if (i > 0) {
-				freemsg(mp);
-				return;
-			}
-		}
-		break;
-
-	case M_IOCTL :
-		pfilwput_ioctl(q, mp);
-		return;
-
-	default :
-		break;
-	}
-
-	putnext(q, mp);
-	return;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfilmodrput                                                 */
-/* Returns:     void                                                        */
-/* Parameters:  q(I)  - pointer to queue                                    */
-/*              mp(I) - pointer to STREAMS message                          */
-/*                                                                          */
-/* This function is called as part of the STREAMS module message processing */
-/* for messages going up to the protocol stack.                             */
-/* ------------------------------------------------------------------------ */
-void pfilmodrput(queue_t *q, mblk_t *mp)
-{
-	union DL_primitives *dl;
-	dl_bind_ack_t *b;
-	int i, flags;
-	qif_t *qif;
-
-	flags = 0;
-	qif = q->q_ptr;
-
-	/* LINTED: E_CONSTANT_CONDITION */
-	PRINT(9,(CE_CONT, "!pfilmodrput(%p,%p) T:%d [%s,%s] qif %p %p\n",
-		 (void *)q, (void *)mp, mp->b_datap->db_type, QTONM(q),
-		 QTONM(OTHERQ(q)), (void *)qif,
-		 (void *)qif->qf_ill));
-
-	switch (MTYPE(mp))
-	{
-#ifdef	DL_IOC_HDR_INFO
-	case M_IOCACK :
-	{
-		struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
-
-		if (iocp->ioc_cmd == DL_IOC_HDR_INFO) {
-			WRITE_ENTER(&pfil_rw);
-			qif_update(qif, mp);
-			RW_EXIT(&pfil_rw);
-		}
-		/*FALLTHROUGH*/
-	}
-#endif	/* DL_IOC_HDR_INFO */
-#ifdef	PFILDEBUG
-	case M_IOCNAK :
-	case M_IOCTL :
-		pfil_printioctl(mp);
-#endif
-		break;
-
-	case M_PROTO :
-	case M_PCPROTO :
-
-		dl = (union DL_primitives *)mp->b_rptr;
-
-		/* LINTED: E_CONSTANT_CONDITION */
-		PRINT(7,(CE_CONT, "!mp:%p pfilmodrput:dl_primitive:%d\n",
-			 (void *)mp, dl->dl_primitive));
-
-		switch (dl->dl_primitive)
-		{
-		case DL_UNITDATA_IND :
-			if ((MLEN(mp) >= sizeof(dl_unitdata_ind_t)) &&
-			    (dl->unitdata_ind.dl_group_address))
-				flags |= PFIL_GROUP;
-			break;
-
-		case DL_SUBS_BIND_ACK :
-			if (qif->qf_waitack > 0) { 
-				dl_subs_bind_ack_t *c;
-
-				c = (dl_subs_bind_ack_t *)dl;
-				if (qif->qf_sap == 0) {
-#if 0
-					qif->qf_sap = c->dl_sap;
-					if (qif->qf_sap < 0)
-						qif->qf_sap = -qif->qf_sap;
-#else
-					cmn_err(CE_NOTE, "c:off %u len %u",
-						c->dl_subs_sap_offset,
-						c->dl_subs_sap_length);
-#endif
-				}
-
-				(void) pfilbind(q);
-				if (qif->qf_waitack > 0)
-					qif->qf_waitack--;
-			}
-			break;
-
-		case DL_BIND_ACK :
-			b = (dl_bind_ack_t *)dl;
-			if (qif->qf_sap == 0) {
-				qif->qf_sap = b->dl_sap;
-				if (qif->qf_sap < 0)
-					qif->qf_sap = -qif->qf_sap;
-			}
-
-			if (b->dl_sap == IEEESAP_SNAP) {
-				qif->qf_waitack++;
-				break;
-			}
-
-			if (!b->dl_sap || b->dl_sap == IP_DL_SAP ||
-			    b->dl_sap == IP6_DL_SAP)
-				(void) pfilbind(q);
-			break;
-
-		default :
-			break;
-		}
-
-		if ((MLEN(mp) < sizeof(dl_unitdata_ind_t)) ||
-		    (dl->dl_primitive != DL_UNITDATA_IND))
-			break;
-
-		/*FALLTHROUGH*/
-	case M_DATA :
-		atomic_add_long(&qif->qf_nr, 1);
-
-		if (qif->qf_ill != NULL) {
-			flags |= PFIL_IN;
-			i = pfil_precheck(q, &mp, flags, qif);
-
-			/* LINTED: E_CONSTANT_CONDITION */
-			PRINT(9, (CE_CONT,
-				  "!pfilmodrput: mp %p pfil_precheck=%d\n",
-				  (void *)mp, i));
-			if (mp == NULL)
-				return;
-			else if (i > 0) {
-				freemsg(mp);
-				return;
-			}
-		}
-		break;
-
-	default :
-		break;
-	}
-
-	putnext(q, mp);
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_drv_priv                                               */
-/* Returns:     int   - 0 == success, EPERM for error.                      */
-/* Parameters:  cr(I) - pointer to credential information                   */
-/*                                                                          */
-/* Checks to see if the caller has enough credentials.                      */
-/* ------------------------------------------------------------------------ */
-static int pfil_drv_priv(cred_t *cr)
-{
-#if SOLARIS2 >= 10
-	return (secpolicy_net_config(cr, B_TRUE));
-#else
-# ifdef sun
-	return (suser(cr) ? 0 : EPERM);
-# else
-	return (suser() ? 0 : EPERM);
-# endif
-#endif
-}
-
-
-/************************************************************************
- * kernel module initialization
- */
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_startup                                                */
-/* Returns:     void                                                        */
-/* Parameters:  None.                                                       */
-/*                                                                          */
-/* Initialise pfil data strutures.                                          */
-/* ------------------------------------------------------------------------ */
-void pfil_startup()
-{
-	pfil_init(&pfh_inet4);
-	pfil_init(&pfh_inet6);
-	pfil_init(&pfh_sync);
-}
--- a/usr/src/uts/common/inet/pfil/pkt.c	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,345 +0,0 @@
-/*
- * Copyright (C) 2000, 2003 by Darren Reed.
- *
- * See the IPFILTER.LICENCE file for details on licencing.
- *
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef __hpux
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-#endif
-
-#include <sys/types.h>
-#include <sys/stream.h>
-#include <sys/cmn_err.h>
-#include <sys/ddi.h>
-#include <sys/rwlock.h>
-#include <sys/socket.h>
-
-#include <net/if.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#if SOLARIS2 >= 8
-# include <netinet/ip6.h>
-#else
-# include <net/if_dl.h>
-#endif
-
-#undef IPOPT_EOL
-#undef IPOPT_NOP
-#undef IPOPT_RR
-#undef IPOPT_LSRR
-#undef IPOPT_SSRR
-#include <inet/common.h>
-#include <inet/ip.h>
-#if SOLARIS2 >= 8
-#include <inet/ip6.h>
-#endif
-#include <inet/ip_ire.h>
-#include <inet/ip_if.h>
-
-#include "compat.h"
-#include "qif.h"
-
-
-extern krwlock_t pfil_rw;
-extern queue_t *pfildq;
-
-#if 1
-/* ------------------------------------------------------------------------ */
-/* Function: pfil_make_dl_packet (mb, ip, dst, ifname, output_q)            */
-/* Returns: On success, datalink msg block.                                 */
-/*	    On failure, NULL.                                               */
-/* Parameters:								    */
-/*	mblk_t *mb: IP message block       				    */
-/*      struct ip *ip: ip header start pointer				    */
-/*      void *dst: destination address.                                     */
-/*            if it is null, destination address is in ip                   */
-/*            for IPV4, the parameter should be an instance of in_addr      */
-/*            for IPV6, the parameter should be an instance of in6_addr     */
-/*      char *ifname: output interface name                                 */
-/*            if neither of dst and ifname is NULL, the routing for dst     */
-/*            should have same interface name as ifname;                    */
-/*            If ifname is NULL,  output interface name is not specified    */
-/*            so it is decided by routing table.                            */
-/*            if dst is NULL(ifname is not NULL), destination address       */
-/*            in IP packet will be used for routing lookup, and the packet  */
-/*            will be send out to interface ifname                          */
-/*      queue_t **output_q: the write queue of pfil module where the        */
-/*            returned message block can be putnext                         */ 
-/*                                                                          */
-/* This function is called to make a datalink message based on the IP       */
-/* message block mb, If the function successfully returns, output_q         */ 
-/* is set to the pfil module's write queue of output interface. Please use  */ 
-/* pfil_send_dl_packet to putnext the returned packet to output_q.          */
-/*                                                                          */
-/* This function will return with a 'lock' held on the qif structure via    */
-/* the PT_ENTER_READ() macro if qif_iflookup succeeds.  This lock is then   */
-/* intended to be released when the queue returned is no longer referenced. */
-/*                                                                          */
-/* fr_fastroute, fr_send_icmp_err, fr_send_reset will call this func to     */
-/* prepare packet.                                                          */
-/*                                                                          */
-/* ip_nexthop[_route] is called to search routing info in this func.        */
-/* ------------------------------------------------------------------------ */
-mblk_t *pfil_make_dl_packet(mb, ip, dst, ifname, output_q)
-mblk_t *mb;
-struct ip *ip;
-void *dst;
-char *ifname;
-queue_t **output_q;
-{
-	mblk_t *mp;
-	qif_t *qif;
-	int ip_inf_bind = 0;
-	char out_ifname_buf[LIFNAMSIZ];
-	struct sockaddr_storage target;
-	int sap;
-
-	if (ip->ip_v == IPV4_VERSION) {
-		struct sockaddr_in *target_in;
-		target_in = (struct sockaddr_in *)&target;
-		sap = IP_DL_SAP;
-		target_in->sin_family = AF_INET;
-		if (dst == NULL)
-			target_in->sin_addr = ip->ip_dst;
-		else {
-			target_in->sin_addr.s_addr = *(ipaddr_t *)dst;
-			if (ifname != NULL)
-				ip_inf_bind = 1;
-		}
-	}
-#ifdef USE_INET6
-	else if (ip->ip_v == IPV6_VERSION) {
-		struct sockaddr_in6 *target_in6;
-		target_in6 = (struct sockaddr_in6 *)&target;
-		sap = IP6_DL_SAP;
-		target_in6->sin6_family = AF_INET6;
-		if (dst == NULL)
-			target_in6->sin6_addr = ((ip6_t *)ip)->ip6_dst;
-		else {
-			bcopy(dst, &target_in6->sin6_addr,
-			      sizeof(struct in6_addr));
-			if (ifname != NULL)
-				ip_inf_bind = 1;
-		}
-	}
-#endif
-
-	if (ip_inf_bind)
-		mp = ip_nexthop((struct sockaddr *)&target, ifname);
-	else {
-		mp = ip_nexthop_route((struct sockaddr *)&target,
-				      out_ifname_buf);
-		if (ifname == NULL)
-			ifname = out_ifname_buf;
-	}
-
-	if (mp == NULL)
-		return NULL;
-
-	/*
-	 * Sometimes the ip_nexthop* functions can't give us a usable packet
-	 * header, for example, when the (nexthop) destination is in need of
-	 * address resolution.  We'd like to punt our packet up to pfild and
-	 * let it send the packet through the normal IP mechanisms, which will
-	 * handle ARP/ND, but if the packet is being sent to an explicit router
-	 * there is no way pfild can indicate that to the IP stack.  So in
-	 * desperation, we discard the packet we are working on and instead
-	 * construct an IP packet with ip_p == 0 to the nexthop router and let
-	 * pfild send that.  This will start the ARP/ND resolution process
-	 * so that next time we need to send a packet to that router, the IRE
-	 * cache is all ready to go.
-	 */
-	if ((MTYPE(mp) == M_PROTO) && (dst != NULL))
-		if ((ip->ip_v == IPV4_VERSION) &&
-		    (ip->ip_dst.s_addr != *(ipaddr_t *)dst)) {
-
-			ASSERT(MTYPE(mb) == M_DATA);
-			if (mb->b_cont != NULL) {
-				freemsg(mb->b_cont);
-				mb->b_cont = NULL;
-			}
-
-			/*
-			 * We don't bother to calculate the IP checksum, raw
-			 * socket will finally do it.
-			 */
-			ip = (struct ip *)mb->b_rptr;
-			ip->ip_hl = 5;
-			ip->ip_tos = 0;
-			ip->ip_len = sizeof (struct ip);
-			ip->ip_id = 0;
-			ip->ip_off = 0;
-			ip->ip_ttl = 1;
-			ip->ip_p = 0;
-			ip->ip_src = *(struct in_addr *)dst;
-			ip->ip_dst = *(struct in_addr *)dst;
-
-			mb->b_wptr = mb->b_rptr + sizeof (struct ip);
-		}
-
-	/* look for output queue */
-	rw_enter(&pfil_rw, RW_READER);
-	qif = (qif_t *)qif_iflookup(ifname, sap);
-	if (qif == NULL) {
-		rw_exit(&pfil_rw);
-		freeb(mp);
-		return NULL;
-	}
-
-	PT_ENTER_READ(&qif->qf_ptl);
-	*output_q = WR(qif->qf_q);
-	rw_exit(&pfil_rw);
-
-	/* OK, by now, we can link the IP message to lay2 header */
-	linkb(mp, mb);
-	mb = mp;
-
-	return mb;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function: pfil_send_dl_packet (output_q, mb)                             */
-/* Returns: void                                                            */
-/* Parameters:								    */
-/*      queue_t *output_q: pfil module's write queue                        */
-/*	mblk_t *mb: Lay2 message block. This parameter should be the return */
-/*                  value of pfil_make_layer2_packet             	    */
-/* This function is called to send the packet returned by                   */
-/* pfil_make_dl_packet.                                                     */
-/* In this function, PT_EXIT_READ is used after the putnext call to release */
-/* the qif structure held by function pfil_make_layer2_packet.              */
-/* ------------------------------------------------------------------------ */
-void pfil_send_dl_packet(output_q, mb)
-queue_t *output_q;
-mblk_t *mb;
-{
-	qif_t *qif;
-
-	/*
-	 * NOTE: It is not permitted to hold a lock across putnext() so we
-	 * use a semaphore-like operation to signal when it is ok to delete
-	 * the qif structure.  With the current locking structure, putnext()
-	 * may be called here after qprocsoff() has been called on output_q,
-	 * but before the queue was completely closed.  See pfilmodclose().
-	 */
-
-	if (MTYPE(mb) == M_PROTO && pfildq != NULL) {
-		/*
-		 * If pfil_make_dl_packet() returned an M_PROTO message it's
-		 * probably an ARP AR_ENTRY_QUERY message, which we can't
-		 * handle, so we just send the IP packet up to pfild to
-		 * transmit it via a raw socket.
-		 */
-		putnext(pfildq, mb->b_cont);
-		mb->b_cont = NULL;
-		freemsg(mb);
-	} else {
-		putnext(output_q, mb);
-	}
-
-	qif = output_q->q_ptr;
-	PT_EXIT_READ(&qif->qf_ptl);
-}
-
-#else /* pfil_sendbuf implementation for no IRE_ILL_CN definition */
-
-/* ------------------------------------------------------------------------ */
-/* Function:    pfil_sendbuf                                                */
-/* Returns:     int  - 0 == success, 1 == failure                           */
-/* Parameters:  m(I) - pointer to streams message                           */
-/*                                                                          */
-/* Output an IPv4 packet to whichever interface has the correct route.      */
-/* ------------------------------------------------------------------------ */
-int pfil_sendbuf(m)
-mblk_t *m;
-{
-	queue_t *q = NULL;
-	struct ip *ip;
-	size_t hlen;
-	ire_t *dir;
-	u_char *s;
-	ill_t *il;
-
-	ip = (struct ip *)m->b_rptr;
-
-#ifdef	MATCH_IRE_DSTONLY
-	dir = ire_route_lookup(ip->ip_dst.s_addr, 0xffffffff, 0, 0,
-				NULL, NULL, NULL,
-				MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|
-				MATCH_IRE_RECURSIVE);
-#else
-	dir = ire_lookup(ip->ip_dst.s_addr);
-#endif
-
-	if (dir) {
-#if SOLARIS2 < 8
-		if (!dir->ire_ll_hdr_mp || !dir->ire_ll_hdr_length)
-#elif (SOLARIS2 >= 8) && (SOLARIS2 <= 10)
-		if (!dir->ire_fp_mp || !dir->ire_dlureq_mp)
-#else
-		if (dir->ire_nce && dir->ire_nce->nce_state != ND_REACHABLE)
-#endif
-			return 2;
-	}
-
-	if (dir) {
-		mblk_t *mp, *mp2;
-
-		il = ire_to_ill(dir);
-		if (!il)
-			return 2;
-#if SOLARIS2 < 8
-		mp = dir->ire_ll_hdr_mp;
-		hlen = dir->ire_ll_hdr_length;
-
-#elif ((SOLARIS2 >= 8) && (SOLARIS2 <= 10)
-		mp = dir->ire_fp_mp;
-		hlen = mp ? mp->b_wptr - mp->b_rptr : 0;
-		mp = dir->ire_dlureq_mp;
-#else
-		mp = dir->ire_nce->nce_fp_mp;
-		hlen = mp ? mp->b_wptr - mp->b_rptr : 0;
-		mp = dir->ire_nce->nce_res_mp;
-#endif
-		s = (u_char *)ip;
-
-		if (hlen &&
-#ifdef	ICK_M_CTL_MAGIC
-		    (il->ill_ick.ick_magic != ICK_M_CTL_MAGIC) &&
-#endif
-		    (s - m->b_datap->db_base) >= hlen) {
-			s -= hlen;
-			m->b_rptr = (u_char *)s;
-			bcopy((char *)mp->b_rptr, (char *)s, hlen);
-		} else {
-			mp2 = copyb(mp);
-			if (!mp2)
-				goto bad_nexthop;
-			mp2->b_cont = m;
-			m = mp2;
-		}
-
-		if (dir->ire_stq)
-			q = dir->ire_stq;
-		else if (dir->ire_rfq)
-			q = WR(dir->ire_rfq);
-		if (q)
-			q = q->q_next;
-		if (q) {
-			RW_EXIT(&pfil_rw);
-			putnext(q, m);
-			READ_ENTER(&pfil_rw);
-			return 0;
-		}
-	}
-bad_nexthop:
-	freemsg(m);
-	return 1;
-}
-#endif /* 1 */
--- a/usr/src/uts/common/inet/pfil/qif.c	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,859 +0,0 @@
-/*
- * Copyright (C) 2000, 2003 by Darren Reed.
- *
- * See the IPFILTER.LICENCE file for details on licencing.
- *
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <sys/systm.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/errno.h>
-#include <sys/uio.h>
-#include <sys/buf.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/modctl.h>
-#include <sys/open.h>
-#include <sys/kmem.h>
-#include <sys/conf.h>
-#include <sys/cmn_err.h>
-#include <sys/stat.h>
-#include <sys/cred.h>
-#include <sys/dditypes.h>
-#include <sys/stream.h>
-#include <sys/poll.h>
-#include <sys/autoconf.h>
-#include <sys/byteorder.h>
-#include <sys/socket.h>
-#include <sys/dlpi.h>
-#include <sys/stropts.h>
-#include <sys/sockio.h>
-#include <sys/ethernet.h>
-#include <net/if.h>
-#if SOLARIS2 >= 6
-# include <net/if_types.h>
-# if SOLARIS2 >= 8
-#  include <netinet/ip6.h>
-# endif
-# include <net/if_dl.h>
-#endif
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <inet/common.h>
-#undef IPOPT_EOL
-#undef IPOPT_NOP
-#undef IPOPT_LSRR
-#undef IPOPT_SSRR
-#undef IPOPT_RR
-#include <inet/ip.h>
-#include <inet/ip_if.h>
-#include <inet/ip_ire.h>
-
-#include "compat.h"
-#include "qif.h"
-#include "pfil.h"
-
-
-#if SOLARIS2 >= 6
-static	size_t	hdrsizes[57][2] = {
-	{ 0, 0 },
-	{ IFT_OTHER, 0 },
-	{ IFT_1822, 0 },
-	{ IFT_HDH1822, 0 },
-	{ IFT_X25DDN, 0 },
-	{ IFT_X25, 0 },
-	{ IFT_ETHER, 14 },
-	{ IFT_ISO88023, 0 },
-	{ IFT_ISO88024, 0 },
-	{ IFT_ISO88025, 0 },
-	{ IFT_ISO88026, 0 },
-	{ IFT_STARLAN, 0 },
-	{ IFT_P10, 0 },
-	{ IFT_P80, 0 },
-	{ IFT_HY, 0 },
-	{ IFT_FDDI, 24 },
-	{ IFT_LAPB, 0 },
-	{ IFT_SDLC, 0 },
-	{ IFT_T1, 0 },
-	{ IFT_CEPT, 0 },
-	{ IFT_ISDNBASIC, 0 },
-	{ IFT_ISDNPRIMARY, 0 },
-	{ IFT_PTPSERIAL, 0 },
-	{ IFT_PPP, 0 },
-	{ IFT_LOOP, 0 },
-	{ IFT_EON, 0 },
-	{ IFT_XETHER, 0 },
-	{ IFT_NSIP, 0 },
-	{ IFT_SLIP, 0 },
-	{ IFT_ULTRA, 0 },
-	{ IFT_DS3, 0 },
-	{ IFT_SIP, 0 },
-	{ IFT_FRELAY, 0 },
-	{ IFT_RS232, 0 },
-	{ IFT_PARA, 0 },
-	{ IFT_ARCNET, 0 },
-	{ IFT_ARCNETPLUS, 0 },
-	{ IFT_ATM, 0 },
-	{ IFT_MIOX25, 0 },
-	{ IFT_SONET, 0 },
-	{ IFT_X25PLE, 0 },
-	{ IFT_ISO88022LLC, 0 },
-	{ IFT_LOCALTALK, 0 },
-	{ IFT_SMDSDXI, 0 },
-	{ IFT_FRELAYDCE, 0 },
-	{ IFT_V35, 0 },
-	{ IFT_HSSI, 0 },
-	{ IFT_HIPPI, 0 },
-	{ IFT_MODEM, 0 },
-	{ IFT_AAL5, 0 },
-	{ IFT_SONETPATH, 0 },
-	{ IFT_SONETVT, 0 },
-	{ IFT_SMDSICIP, 0 },
-	{ IFT_PROPVIRTUAL, 0 },
-	{ IFT_PROPMUX, 0 },
-};
-#endif /* SOLARIS2 >= 6 */
-
-
-#if SOLARIS2 <= 6
-# include <sys/kmem_impl.h>
-#endif
-#if SOLARIS2 >= 10
-extern krwlock_t ill_g_lock;
-#endif
-
-#define	SAPNAME(x)	((x)->qf_sap == 0x0800 ? "IPv4" : \
-			 (x)->qf_sap == 0x86dd ? "IPv6" : "??")
-
-static	int		qif_num = 0;
-static	kmem_cache_t	*qif_cache = NULL;
-
-qif_t	*qif_head;
-int	qif_verbose = 0;
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    qif_startup                                                 */
-/* Returns:     int - 0 == success, -1 == failure                           */
-/* Parameters:  None.                                                       */
-/*                                                                          */
-/* Perform any initialisation of data structures related to managing qif's  */
-/* that is deemed necessary.                                                */
-/* ------------------------------------------------------------------------ */
-int qif_startup()
-{
-
-	qif_head = NULL;
-	qif_cache = kmem_cache_create("qif_head_cache", sizeof(qif_t), 8,
-				      NULL, NULL, NULL, NULL, NULL, 0);
-	if (qif_cache == NULL) {
-		cmn_err(CE_NOTE, "qif_startup:kmem_cache_create failed");
-		return -1;
-	}
-	return 0;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    qif_stop                                                    */
-/* Returns:     void                                                        */
-/* Parameters:  None.                                                       */
-/*                                                                          */
-/* Deallocate all qif_t's allocated and clean up any other data structures  */
-/* required in order to 'shut down' this part of the pfil module.           */
-/* ------------------------------------------------------------------------ */
-void qif_stop()
-{
-	kmem_cache_destroy(qif_cache);
-	qif_cache = NULL;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    q_to_ill                                                    */
-/* Returns:     void * - NULL == failure, else pointer to ill               */
-/* Parameters:  rq(I) - pointer to STREAMS read queue                       */
-/* Locks:       pfil_rw                                                     */
-/*                                                                          */
-/* Given a pointer to a queue, try and find the ill which owns it.          */
-/* ------------------------------------------------------------------------ */
-void *q_to_ill(rq)
-queue_t *rq;
-{
-#ifndef	IRE_ILL_CN
-	ill_t *ill = NULL;
-	queue_t *qu, *wq;
-
-	wq = OTHERQ(rq);
-	if (rq) {
-#if SOLARIS2 >= 10
-		ill_walk_context_t ctx;
-
-		rw_enter(&ill_g_lock, RW_READER);
-		for (ill = ILL_START_WALK_ALL(&ctx); ill != NULL;
-		     ill = ill_next(&ctx, ill))
-#else
-		for (ill = ill_g_head; ill != NULL; ill = ill->ill_next)
-#endif
-		{
-			if (ill->ill_rq == NULL || ill->ill_wq == NULL)
-				continue;
-			if (ill->ill_rq == RD(rq)->q_next)
-				break;
-			for (qu = WR(ill->ill_rq); qu; qu = qu->q_next)
-				if ((qu->q_ptr == rq->q_ptr) || (qu == wq))
-					break;
-			if (qu != NULL)
-				break;
-			for (qu = ill->ill_rq; qu; qu = qu->q_next)
-				if (qu->q_ptr == rq->q_ptr)
-					break;
-			if (qu != NULL)
-				break;
-		}
-	}
-#if SOLARIS2 >= 10
-	rw_exit(&ill_g_lock);
-#endif
-	return ill;
-#else /* IRE_ILL_CN */
-	s_ill_t *ill = NULL;
-
-	if (!rq)
-		return 0;
-
-	ASSERT(rq->q_flag & QREADR);
-
-	mutex_enter(&s_ill_g_head_lock);
-	for (ill = s_ill_g_head; ill; ill = ill->ill_next)
-		if (ill->ill_rq == rq)
-			break;
-	mutex_exit(&s_ill_g_head_lock);
-
-	return ill;
-#endif
-}
-
-
-#ifndef	IRE_ILL_CN
-/* ------------------------------------------------------------------------ */
-/* Function:    qif_ire_walker                                              */
-/* Returns:     void                                                        */
-/* Parameters:  ire(I) - pointer to an ire_t                                */
-/*              arg(I) - pointer to a qif                                   */
-/*                                                                          */
-/* This function gets called by the ire-walking function for each ire in    */
-/* table.  We enumerate through the ire looking for cached fastpath headers */
-/* on a given NIC (the qif) so we can update qf_hl from its size.           */
-/* ------------------------------------------------------------------------ */
-void
-qif_ire_walker(ire, arg)
-	ire_t *ire;
-	void *arg;
-{
-	qif_t *qif = arg;
-
-	if ((ire->ire_type == IRE_CACHE) &&
-#if SOLARIS2 >= 6
-	    (ire->ire_ipif != NULL) &&
-	    (ire->ire_ipif->ipif_ill == qif->qf_ill)
-#else
-	    (ire_to_ill(ire) == qif->qf_ill)
-#endif
-	    ) {
-#if SOLARIS2 < 8
-		mblk_t *m = ire->ire_ll_hdr_mp;
-#elif (SOLARIS2 >= 8) && (SOLARIS2 <= 10)
-		mblk_t *m = ire->ire_fp_mp;
-#else
-		mblk_t *m = ire->ire_nce->nce_fp_mp;
-#endif
-		if (m != NULL)
-			qif->qf_hl = m->b_wptr - m->b_rptr;
-	}
-}
-#endif
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    qif_attach                                                  */
-/* Returns:     int  - 0 == success, -1 == error in attaching qif_t to q    */
-/* Parameters:  rq(I) - pointer to STREAMS read queue                       */
-/* Write Lock:  pfil_rw                                                     */
-/*                                                                          */
-/* Attempt to bind a qif_t structure to a specific interface given the      */
-/* queue pointer.  Assumes the queue already has a qif_t structure tagged   */
-/* against it.                                                              */
-/* ------------------------------------------------------------------------ */
-int
-qif_attach(rq)
-	queue_t *rq;
-{
-	packet_filter_hook_t *pfh;
-	qif_t *qif;
-#ifdef IRE_ILL_CN
-	s_ill_t *ill;
-#else
-	ill_t *ill;
-#endif
-
-	WRITE_ENTER(&pfil_rw);
-	/*
-	 * Can we map the queue to a specific ill?  If not, go no futher, we
-	 * are only interested in being associated with queues that we can
-	 * recognise as being used for IP communication of some sort.
-	 */
-	ill = q_to_ill(rq);
-	if (ill == NULL) {
-		if (qif_verbose > 0)
-			cmn_err(CE_NOTE,
-				"PFIL: cannot find interface for rq %p",
-				(void *)rq);
-		RW_EXIT(&pfil_rw);
-		return -1;
-	}
-
-	qif = rq->q_ptr;
-#ifndef IRE_ILL_CN
-#if SOLARIS2 < 8
-	qif->qf_hl = ill->ill_hdr_length;
-#else
-	if ((ill->ill_type > 0) && (ill->ill_type < 0x37) &&
-	    (hdrsizes[ill->ill_type][0] == ill->ill_type))
-		qif->qf_hl = hdrsizes[ill->ill_type][1];
-
-	if (qif->qf_hl == 0 && ill->ill_type != IFT_OTHER) {
-		cmn_err(CE_WARN,
-			"!Unknown layer 2 header size for %s type %d sap %x\n",
-			qif->qf_name, ill->ill_type, ill->ill_sap);
-	}
-#endif
-#endif /* IRE_ILL_CN */
-
-	/*
-	 * Protect against the qif_t being bound against an interface, twice
-	 * by getting a lock on setting qf_bound and don't release it until
-	 * all the information has been set with qf_bound finally set to 1
-	 * after that.
-	 */
-	if (qif->qf_bound == 1) {
-		RW_EXIT(&pfil_rw);
-		return 0;
-	}
-
-	qif->qf_sap = ill->ill_sap;
-#ifndef IRE_ILL_CN
-	qif->qf_ppa = ill->ill_ppa;
-#endif
-#ifdef icmp_nextmtu
-	qif->qf_max_frag = ill->ill_max_frag;
-#endif
-	(void) strncpy(qif->qf_name, ill->ill_name, sizeof(qif->qf_name));
-	qif->qf_name[sizeof(qif->qf_name) - 1] = '\0';
-	qif->qf_ill = ill;
-	qif->qf_bound = 1;
-	qif_ipmp_syncslave(qif, qif->qf_sap);
-	RW_EXIT(&pfil_rw);
-
-	READ_ENTER(&pfh_sync.ph_lock);
-
-	pfh = pfil_hook_get(PFIL_IN, &pfh_sync);
-	for (; pfh; pfh = pfh->pfil_next)
-		if (pfh->pfil_func)
-			(void) (*pfh->pfil_func)(NULL, 0, qif, 0, qif, NULL);
-
-	RW_EXIT(&pfh_sync.ph_lock);
-
-	if (qif_verbose > 0)
-		cmn_err(CE_NOTE, "PFIL: attaching [%s] - %s", qif->qf_name,
-			SAPNAME(qif));
-#if SOLARIS2 <= 8
-	ire_walk(qif_ire_walker, qif);
-#else
-# ifndef IRE_ILL_CN
-	ire_walk(qif_ire_walker, (char *)qif);
-# endif
-#endif
-	return 0;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    qif_new                                                     */
-/* Returns:     qif_t * - NULL == failure, else pointer to qif_t            */
-/* Parameters:  q(I) - pointer to STREAMS queue                             */
-/*                                                                          */
-/* Allocate a new qif struct, give it a unique number and add it to the     */
-/* list of registered qif_t's for the given queue.  Along the way, if we    */
-/* find an existing qif_t for this queue, return that instead.              */
-/* ------------------------------------------------------------------------ */
-qif_t *
-qif_new(q, mflags)
-	queue_t *q;
-	int mflags;
-{
-	qif_t *qif;
-
-	qif = kmem_cache_alloc(qif_cache, mflags);
-	if (qif == NULL) {
-		cmn_err(CE_NOTE, "PFIL: malloc(%d) for qif_t failed",
-			(int)sizeof(qif_t));
-		return NULL;
-	}
-
-	bzero((char *)qif, sizeof(*qif));
-	mutex_init(&qif->qf_ptl.pt_lock, NULL, MUTEX_DRIVER, NULL);
-	cv_init(&qif->qf_ptl.pt_cv, NULL, CV_DRIVER, NULL);
-	qif->qf_qifsz = sizeof(*qif);
-	qif->qf_q = q;
-	qif->qf_oq = OTHERQ(q);
-	WRITE_ENTER(&pfil_rw);
-	qif->qf_num = qif_num++;
-	qif->qf_next = qif_head;
-	qif_head = qif;
-	RW_EXIT(&pfil_rw);
-	(void) sprintf(qif->qf_name, "QIF%x", qif->qf_num);
-	return qif;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    qif_delete                                                  */
-/* Returns:     void                                                        */
-/* Parameters:  None.                                                       */
-/* Write Locks: pfil_rw                                                     */
-/*                                                                          */
-/* Remove a qif structure from the list of recognised qif's.                */
-/*                                                                          */
-/* NOTE: The locking structure used here on qif's is to protect their use   */
-/* by the pkt.c functions for sending out a packet.  It is possible that a  */
-/* packet will be processed on one queue and need to be output on another   */
-/* and given we cannot hold a lock across putnext() we need to use a P-V    */
-/* like algorithm for locking.  The PT_* macros come from the PTY code.     */
-/* In the fullness of time, this function should be rewritten to make sure  */
-/* that it is not posible to find the qif before we call the PT_* macros    */
-/* and call qprocsoff().                                                    */
-/* ------------------------------------------------------------------------ */
-/*ARGSUSED*/
-void qif_delete(qif, q)
-qif_t *qif;
-queue_t *q;
-{
-	packet_filter_hook_t *pfh;
-	qif_t **qp;
-	int rm = 0;
-
-	if (qif == NULL)
-		return;
-
-	WRITE_ENTER(&pfil_rw);
-	PT_ENTER_WRITE(&qif->qf_ptl);
-
-	if (qif->qf_bound == 1 && qif_verbose > 0)
-		cmn_err(CE_NOTE, "PFIL: detaching [%s] - %s", qif->qf_name,
-			SAPNAME(qif));
-
-	for (qp = &qif_head; *qp; qp = &(*qp)->qf_next)
-		if (*qp == qif) {
-			*qp = qif->qf_next;
-			rm = 1;
-			break;
-		}
-	PT_EXIT_WRITE(&qif->qf_ptl);
-	RW_EXIT(&pfil_rw);
-
-	if (qif->qf_ill) {
-		READ_ENTER(&pfh_sync.ph_lock);
-		pfh = pfil_hook_get(PFIL_OUT, &pfh_sync);
-		for (; pfh; pfh = pfh->pfil_next)
-			if (pfh->pfil_func)
-				(void) (*pfh->pfil_func)(NULL, 0, qif,
-							 1, qif, NULL);
-		RW_EXIT(&pfh_sync.ph_lock);
-	}
-
-	if (rm) {
-		if (qif->qf_addrset != NULL)
-			freeb(qif->qf_addrset);
-		mutex_destroy(&qif->qf_ptl.pt_lock);
-		cv_destroy(&qif->qf_ptl.pt_cv);
-
-		if (qif->qf_qifsz == sizeof(*qif))
-			kmem_cache_free(qif_cache, qif);
-		else {
-			KMFREE(qif, qif->qf_qifsz);
-		}
-	}
-	return;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    qif_iflookup                                                */
-/* Returns:     void *  - NULL == search failed, else pointer to qif_t      */
-/* Parameters:  name(I) - pointer to the name                               */
-/*              sap(I)  - SAP value                                         */
-/* Locks:       pfil_rw                                                     */
-/*                                                                          */
-/* Search the list of registered qif_t's for a match based on the name and  */
-/* the SAP and return a pointer to the matching entry.                      */
-/* ------------------------------------------------------------------------ */
-void *qif_iflookup(char *name, int sap)
-{
-	qif_t *qif;
-
-	for (qif = qif_head; qif; qif = qif->qf_next)
-		if ((!sap || (qif->qf_sap == sap)) &&
-		    !strcmp(qif->qf_name, name))
-			break;
-	return qif;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    qif_update                                                  */
-/* Returns:     void                                                        */
-/* Parameters:  qif(I) - pointer to qif_t structure                         */
-/*              mp(I)  - pointer to STREAMS message                         */
-/* Locks:       pfil_rw                                                     */
-/*                                                                          */
-/* This function attempts to force an update of the qf_sap and qf_hl fields */
-/* using information that is in the STREAMS message and/or the ill_t.  This */
-/* function should only be called if the mblk is a DL_IOC_HDR_INFO message. */
-/* ------------------------------------------------------------------------ */
-void qif_update(qif, mp)
-qif_t *qif;
-mblk_t *mp;
-{
-#ifdef IRE_ILL_CN
-	s_ill_t *ill;
-#else
-	ill_t *ill;
-#endif
-
-	ill = qif->qf_ill;
-	if (ill == NULL)
-		return;
-
-	if (mp->b_datap->db_type == M_IOCACK && mp->b_cont) {
-		mp = mp->b_cont;
-		if (mp->b_datap->db_type == M_PROTO && mp->b_cont) {
-			mp = mp->b_cont;
-			if (mp->b_datap->db_type == M_DATA) {
-				qif->qf_hl = mp->b_wptr - mp->b_rptr;
-			}
-		}
-	}
-
-	/*
-	 * If we still have a 0 size expected fasthpath header length, check
-	 * the ill structure to see if we can use it to now make a better
-	 * guess about what to use.
-	 */
-	qif->qf_sap = ill->ill_sap;
-#ifndef IRE_ILL_CN
-	if (qif->qf_hl == 0) {
-#if SOLARIS2 < 8
-		qif->qf_hl = ill->ill_hdr_length;
-#else
-		if ((ill->ill_type > 0) && (ill->ill_type < 0x37) &&
-		    (hdrsizes[ill->ill_type][0] == ill->ill_type))
-			qif->qf_hl = hdrsizes[ill->ill_type][1];
-#endif
-	}
-#endif
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    qif_walk                                                    */
-/* Returns:     qif_t *  - NULL == search failed, else pointer to qif_t     */
-/* Parameters:  qfp(IO) - pointer to the name                               */
-/*                                                                          */
-/* NOTE: it is assumed the caller has a lock on pfil_rw                     */
-/*                                                                          */
-/* Provide a function to enable the caller to enumerate through all of the  */
-/* qif_t's without being aware of the internal data structure used to store */
-/* them in.                                                                 */
-/* ------------------------------------------------------------------------ */
-qif_t *qif_walk(qif_t **qfp)
-{
-	struct qif *qf, *qf2;
-
-	if (qfp == NULL)
-		return NULL;
-
-	qf = *qfp;
-	if (qf == NULL)
-		*qfp = qif_head;
-	else {
-		/*
-		 * Make sure the pointer being passed in exists as a current
-		 * object before returning its next value.
-		 */
-		for (qf2 = qif_head; qf2 != NULL; qf2 = qf2->qf_next)
-			if (qf2 == qf)
-				break;
-		if (qf2 == NULL)
-			*qfp = NULL;
-		else
-			*qfp = qf->qf_next;
-	}
-	return *qfp;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    qif_ipmp_update                                             */
-/* Returns:     void                                                        */
-/* Parameters:  ipmpconf(I) - pointer to an ill to match against            */
-/*                                                                          */
-/* Take an IPMP configuration string passed in to update the pfil config.   */
-/* The string may either indicate that an IPMP interface is to be deleted   */
-/* ("ipmp0=" - no NICs after the right of the '=') or created/changed if    */
-/* there is text after the '='.                                             */
-/* ------------------------------------------------------------------------ */
-void qif_ipmp_update(char *ipmpconf)
-{
-	qif_t *qif, *qf;
-	int len, sap;
-	char *s;
-
-	sap = ETHERTYPE_IP;
-	if (!strncmp(ipmpconf, "v4:", 3)) {
-		ipmpconf += 3;
-	} else if (!strncmp(ipmpconf, "v6:", 3)) {
-#if SOLARIS2 >= 8
-		sap = IP6_DL_SAP;
-		ipmpconf += 3;
-#else
-		return;
-#endif
-	}
-
-	s = strchr(ipmpconf, '=');
-	if (s != NULL) {
-		if (*(s + 1) == '\0')
-			*s = '\0';
-		else
-			*s++ = '\0';
-	}
-	if (s == NULL || *s == NULL) {
-		qif_ipmp_delete(ipmpconf);
-		return;
-	}
-
-	len = sizeof(qif_t) + strlen(s) + 1;
-	KMALLOC(qif, qif_t *, len, KM_NOSLEEP);
-	if (qif == NULL) {
-		cmn_err(CE_NOTE, "PFIL: malloc(%d) for qif_t failed", len);
-		return;
-	}
-
-	WRITE_ENTER(&pfil_rw);
-	for (qf = qif_head; qf; qf = qf->qf_next) 
-		if (strcmp(qf->qf_name, ipmpconf) == 0)
-			break;
-
-	if (qf == NULL) {
-		qf = qif;
-		qif->qf_next = qif_head;
-		qif_head = qif;
-
-		qif->qf_sap = sap;
-		qif->qf_flags |= QF_IPMP;
-		qif->qf_qifsz = len;
-		qif->qf_members = (char *)qif + sizeof(*qif);
-		(void) strcpy(qif->qf_name, ipmpconf);
-	} else {
-		KMFREE(qif, len);
-		qif = qf;
-	}
-
-	(void) strcpy(qif->qf_members, s);
-
-	qif_ipmp_syncmaster(qif, sap);
-
-	RW_EXIT(&pfil_rw);
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    qif_ipmp_delete                                             */
-/* Returns:     void                                                        */
-/* Parameters:  qifname(I) - pointer to name of qif to delete               */
-/*                                                                          */
-/* Search for a qif structure that is named to match qifname, remove all    */
-/* references to it by others, delink and free it.                          */
-/* ------------------------------------------------------------------------ */
-void qif_ipmp_delete(char *qifname)
-{
-	packet_filter_hook_t *pfh;
-	qif_t *qf, **qfp, *qif;
-
-	WRITE_ENTER(&pfil_rw);
-	for (qfp = &qif_head; (qif = *qfp) != NULL; qfp = &qif->qf_next) {
-		if ((qif->qf_flags & QF_IPMP) == 0)
-			continue;
-		if (strcmp(qif->qf_name, qifname) == 0) {
-			*qfp = qif->qf_next;
-			for (qf = qif_head; qf != NULL; qf = qf->qf_next)
-				if (qf->qf_ipmp == qif)
-					qf->qf_ipmp = NULL;
-			break;
-		}
-	}
-	RW_EXIT(&pfil_rw);
-
-	if (qif != NULL) {
-		pfh = pfil_hook_get(PFIL_OUT, &pfh_sync);
-		for (; pfh; pfh = pfh->pfil_next)
-			if (pfh->pfil_func)
-				(void) (*pfh->pfil_func)(NULL, 0, qif, 1,
-							 qif, NULL);
-
-		KMFREE(qif, qif->qf_qifsz);
-	}
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    qif_ipmp_syncmaster                                         */
-/* Returns:     void                                                        */
-/* Parameters:  updated(I) - pointer to updated qif structure               */
-/* Locks:       pfil_rw                                                     */
-/*                                                                          */
-/* This function rechecks all the qif structures that aren't defined for    */
-/* IPMP to see if they are indeed members of the group pointed to by        */
-/* updated.  Ones that currently claim to be in updated are reset and       */
-/* rechecked in case they have become excluded. This function should be     */
-/* called for any new IPMP qif's created or when an IPMP qif changes.       */
-/* ------------------------------------------------------------------------ */
-void qif_ipmp_syncmaster(qif_t *updated, const int sap)
-{
-	char *s, *t;
-	qif_t *qf;
-
-	for (qf = qif_head; qf != NULL; qf = qf->qf_next)  {
-		if ((qf->qf_flags & QF_IPMP) != 0)
-			continue;
-		if (qf->qf_sap != sap)
-			continue;
-		if (qf->qf_ipmp == updated)
-			qf->qf_ipmp = NULL;
-		for (s = updated->qf_members; s != NULL; ) {
-			t = strchr(s, ',');
-			if (t != NULL)
-				*t = '\0';
-			if (strcmp(qf->qf_name, s) == 0)
-				qf->qf_ipmp = updated;
-			if (t != NULL)
-				*t++ = ',';
-			s = t;
-		}
-	}
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    qif_ipmp_syncslave                                          */
-/* Returns:     void                                                        */
-/* Parameters:  target(I) - pointer to updated qif structure                */
-/* Locks:       pfil_rw                                                     */
-/*                                                                          */
-/* Check through the list of qif's to see if there is an IPMP with a member */
-/* list that includes the one named by target.                              */
-/* ------------------------------------------------------------------------ */
-void qif_ipmp_syncslave(qif_t *target, const int sap)
-{
-	char *s, *t;
-	qif_t *qf;
-
-	target->qf_ipmp = NULL;
-
-	/*
-	 * Recheck the entire list of qif's for any references to the one
-	 * we have just created/updated (updated).
-	 */
-	for (qf = qif_head; qf != NULL; qf = qf->qf_next)  {
-		if ((qf->qf_flags & QF_IPMP) == 0)
-			continue;
-		if (qf->qf_sap != sap)
-			continue;
-		for (s = qf->qf_members; s != NULL; ) {
-			t = strchr(s, ',');
-			if (t != NULL)
-				*t = '\0';
-			if (strcmp(target->qf_name, s) == 0)
-				target->qf_ipmp = qf;
-			if (t != NULL)
-				*t++ = ',';
-			s = t;
-			if (target->qf_ipmp == qf)
-				break;
-		}
-	}
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Function:    qif_hl_set                                                  */
-/* Returns:     void                                                        */
-/* Parameters:  ipmpconf(I) - string with header length setting for NIC     */
-/*                                                                          */
-/* For NICs that we cannot automatically determine the MAC header length of */
-/* we provide a manual crook to achieve that with.  The input syntax for    */
-/* the string is "[v4:|v6:]<ifname>=<length>"                               */
-/* ------------------------------------------------------------------------ */
-void qif_hl_set(char *ipmpconf)
-{
-	qif_t *qf;
-	char *s;
-
-	if (!strncmp(ipmpconf, "v4:", 3)) {
-		ipmpconf += 3;
-	} else if (!strncmp(ipmpconf, "v6:", 3)) {
-#if SOLARIS2 >= 8
-		ipmpconf += 3;
-#else
-		return;
-#endif
-	}
-
-	s = strchr(ipmpconf, '=');
-	if (s != NULL) {
-		if (*(s + 1) == '\0')
-			*s = '\0';
-		else
-			*s++ = '\0';
-	}
-	if (s == NULL || *s == NULL)
-		return;
-
-	READ_ENTER(&pfil_rw);
-	for (qf = qif_head; qf; qf = qf->qf_next) 
-		if (strcmp(qf->qf_name, ipmpconf) == 0)
-			break;
-
-	if (qf != NULL) {
-		int hl = 0;
-
-		for (; *s != '\0'; s++) {
-			char c = *s;
-
-			if (c < '0' || c > '9')
-				return;
-			hl *= 10;
-			hl += c - '0'; 
-		}
-		qf->qf_hl = hl;
-	}
-
-	RW_EXIT(&pfil_rw);
-}
--- a/usr/src/uts/common/inet/pfil/qif.h	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2003 by Darren Reed.
- *
- * See the IPFILTER.LICENCE file for details on licencing.
- *
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef sun
-# include <sys/dditypes.h>
-# include <sys/ptms.h>
-#endif
-
-
-#ifdef	IRE_ILL_CN
-typedef	union	{
-	struct sockaddr_in qfa_in;
-	struct sockaddr_in6 qfa_in6;
-} qfa_t;
-# define	qfa_family	qfa_in.sin_family
-# define	qfa_v4addr	qfa_in.sin_addr
-# define	qfa_v6addr	qfa_in6.sin6_addr
-#else
-# define	QF_IPIF(x)	((ill_t *)(x)->qf_ill)->ill_ipif
-# define	qf_netmask	QF_IPIF->ipif_net_mask
-#  define	qf_dstaddr	QF_IPIF->ipif_pp_dst_addr
-# if SOLARIS2 <= 7
-#  define	qf_localaddr	QF_IPIF->ipif_local_addr
-#  define	qf_broadaddr	QF_IPIF->ipif_broadcast_addr
-# else
-#  define	qf_localaddr	QF_IPIF->ipif_lcl_addr
-#  define	qf_broadaddr	QF_IPIF->ipif_brd_addr
-# endif
-# ifdef	USE_INET6
-#  define	qf_v6netmask	QF_IPIF->ipif_v6net_mask
-#  define	qf_v6broadaddr	QF_IPIF->ipif_v6brd_addr
-#  define	qf_v6dstaddr	QF_IPIF->ipif_v6pp_dst_addr
-# endif
-#endif
-
-typedef	struct	s_ill_s	{
-	struct	s_ill_s	*ill_next;	/* Chained in at s_ill_g_head. */
-	kmutex_t	s_ill_lock;
-	char	ill_name[LIFNAMSIZ];	/* Our name. */
-	t_uscalar_t	ill_sap;	/* IP_DL_SAP or IP6_DL_SAP */
-	queue_t	*ill_rq;		/* lower stream read queue */
-	union {
-		struct sockaddr_in in;
-		struct sockaddr_in6 in6;
-	} localaddr;
-	union {
-		struct sockaddr_in in;
-		struct sockaddr_in6 in6;
-	} netmask;
-	union {
-		struct sockaddr_in in;
-		struct sockaddr_in6 in6;
-	} broadaddr;
-	union {
-		struct sockaddr_in in;
-		struct sockaddr_in6 in6;
-	} dstaddr;
-	uint_t	mtu;
-} s_ill_t;
-
-typedef	struct	qif	{
-	/* for alignment reasons, the lock is first. */
-	kmutex_t	qf_lock;
-	struct qifplock {
-		kmutex_t	pt_lock;
-#ifdef sun
-		kcondvar_t	pt_cv;
-#endif
-		int		pt_refcnt;
-		int		pt_access;
-	} qf_ptl;
-	struct	qif	*qf_next;
-	struct	qif	*qf_ipmp;	/* Pointer to group qif */
-	void		*qf_ill;
-	queue_t		*qf_q;
-	queue_t		*qf_oq;
-	/* statistical data */
-	u_long		qf_nr;
-	u_long		qf_nw;
-	u_long		qf_bad;
-	u_long		qf_copy;
-	u_long		qf_copyfail;
-	u_long		qf_drop;
-	u_long		qf_notip;
-	u_long		qf_nodata;
-	u_long		qf_notdata;
-	/* other data for the NIC on this queue */
-	size_t		qf_qifsz;
-	size_t		qf_hl;		/* header length */
-	u_int		qf_num;
-	u_int		qf_ppa;		/* Physical Point of Attachment */
-	int		qf_sap;		/* Service Access Point */
-	int		qf_bound;
-	int		qf_flags;
-	int		qf_waitack;
-	int		qf_max_frag;	/* MTU for interface */
-	char		qf_name[LIFNAMSIZ];
-	char		*qf_members;
-
-	/* ON(10, NV) specific */
-	mblk_t		*qf_addrset;
-	size_t		qf_off;
-	mblk_t		*qf_m;
-	void		*qf_data;
-} qif_t;
-
-
-typedef	struct	qpktinfo	{
-	/* data that changes per-packet */
-	qif_t		*qpi_real;	/* the real one on the STREAM */
-	void		*qpi_ill;	/* COPIED */
-	mblk_t		*qpi_m;
-	queue_t		*qpi_q;
-	char		*qpi_name;	/* points to qf_real->qf_name */
-	void		*qpi_data;	/* where layer 3 header starts */
-	size_t		qpi_off;
-	size_t		qpi_hl;		/* COPIED */
-	u_int		qpi_ppa;	/* COPIED */
-	u_int		qpi_num;	/* COPIED */
-	int		qpi_flags;	/* COPIED */
-	int		qpi_max_frag;	/* COPIED */
-} qpktinfo_t;
-
-
-#ifdef sun
-# if SOLARIS2 <= 7
-#  define	QF_V4_ADDR(x)	\
-			((ill_t *)(x)->qf_ill)->ill_ipif->ipif_local_addr
-#  define	QF_V4_BROADCAST(x)	\
-			((ill_t *)(x)->qf_ill)->ill_ipif->ipif_broadcast_addr
-# else
-#  define	QF_V4_ADDR(x)	\
-			((ill_t *)(x)->qf_ill)->ill_ipif->ipif_lcl_addr
-#  define	QF_V4_BROADCAST(x)	\
-			((ill_t *)(x)->qf_ill)->ill_ipif->ipif_brd_addr
-# endif
-# define	QF_V4_NETMASK(x)	\
-			((ill_t *)(x)->qf_ill)->ill_ipif->ipif_net_mask
-# define	QF_V4_PEERADDR(x)	\
-			((ill_t *)(x)->qf_ill)->ill_ipif->ipif_pp_dst_addr
-# ifdef	USE_INET6
-#  define	QF_V6_BROADCAST(x)	\
-			((ill_t *)(x)->qf_ill)->ill_ipif->ipif_v6brd_addr
-#  define	QF_V6_NETMASK(x)	\
-			((ill_t *)(x)->qf_ill)->ill_ipif->ipif_v6net_mask
-#  define	QF_V6_PEERADDR(x)	\
-			((ill_t *)(x)->qf_ill)->ill_ipif->ipif_v6pp_dst_addr
-# endif
-#endif
-
-#ifdef __hpux
-# define	QF_V4_ADDR(x)		((ifinfo_t *)(x)->qf_ill)->ifi_addr[0]
-# define	QF_V4_BROADCAST(x)	0
-# define	QF_V4_NETMASK(x)	0xffffffff
-# define	QF_V4_PEERADDR(x)	0
-# ifdef	USE_INET6
-#  define	QF_V6_BROADCAST(x)	0
-#  define	QF_V6_NETMASK(x)	0
-#  define	QF_V6_PEERADDR(x)	0
-# endif
-#endif
-
-
-#define	QF_GROUP	0x0001
-#define	QF_IPMP		0x0002
-
-extern void *q_to_ill(queue_t *);
-extern struct qif *qif_new(queue_t *, int);
-extern int qif_attach(queue_t *);
-extern void qif_delete(struct qif *, queue_t *);
-extern int qif_startup(void);
-extern void qif_stop(void);
-extern void *qif_iflookup(char *, int);
-
-#ifdef __hpux
-struct irinfo_s;
-extern void *ir_to_ill(struct irinfo_s *ir);
-#endif
-extern struct qif *qif_walk(struct qif **);
-extern struct qif *qif_head;
-extern int qif_verbose;
-extern void qif_update(struct qif *, mblk_t *);
-extern void qif_nd_init(void);
-extern void qif_hl_set(char *);
-extern void qif_ipmp_delete(char *);
-extern void qif_ipmp_update(char *);
-extern void qif_ipmp_syncmaster(struct qif *, const int);
-extern void qif_ipmp_syncslave(struct qif *, const int);
-
-#ifndef IRE_ILL_CN
-extern void qif_ire_walker(ire_t *, void *);
-#endif
-
-extern kmutex_t s_ill_g_head_lock;
-extern s_ill_t *s_ill_g_head;
--- a/usr/src/uts/common/inet/tcp.h	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/tcp.h	Fri Oct 20 16:37:58 2006 -0700
@@ -568,6 +568,9 @@
 extern void	tcp_time_wait_collector(void *arg);
 extern int	tcp_snmp_get(queue_t *, mblk_t *);
 extern int	tcp_snmp_set(queue_t *, int, int, uchar_t *, int len);
+extern mblk_t	*tcp_xmit_mp(tcp_t *tcp, mblk_t *mp, int32_t max_to_send,
+		    int32_t *offset, mblk_t **end_mp, uint32_t seq,
+		    boolean_t sendall, uint32_t *seg_len, boolean_t rexmit);
 /*
  * The TCP Fanout structure.
  * The hash tables and their linkage (tcp_*_hash_next, tcp_ptp*hn) are
--- a/usr/src/uts/common/inet/tcp/tcp.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/tcp/tcp.c	Fri Oct 20 16:37:58 2006 -0700
@@ -45,6 +45,7 @@
 #include <sys/xti_inet.h>
 #include <sys/cmn_err.h>
 #include <sys/debug.h>
+#include <sys/sdt.h>
 #include <sys/vtrace.h>
 #include <sys/kmem.h>
 #include <sys/ethernet.h>
@@ -95,6 +96,7 @@
 #include <inet/ip_ftable.h>
 #include <inet/ip_if.h>
 #include <inet/ipp_common.h>
+#include <inet/ip_netinfo.h>
 #include <sys/squeue.h>
 #include <inet/kssl/ksslapi.h>
 #include <sys/tsol/label.h>
@@ -222,6 +224,13 @@
  * only exception is tcp_xmit_listeners_reset() which is called
  * directly from IP and needs to policy check to see if TH_RST
  * can be sent out.
+ *
+ * PFHooks notes :
+ *
+ * For mdt case, one meta buffer contains multiple packets. Mblks for every
+ * packet are assembled and passed to the hooks. When packets are blocked,
+ * or boundary of any packet is changed, the mdt processing is stopped, and
+ * packets of the meta buffer are send to the IP path one by one.
  */
 
 extern major_t TCP6_MAJ;
@@ -919,9 +928,6 @@
 		    int num_sack_blk);
 static void	tcp_wsrv(queue_t *q);
 static int	tcp_xmit_end(tcp_t *tcp);
-static mblk_t	*tcp_xmit_mp(tcp_t *tcp, mblk_t *mp, int32_t max_to_send,
-		    int32_t *offset, mblk_t **end_mp, uint32_t seq,
-		    boolean_t sendall, uint32_t *seg_len, boolean_t rexmit);
 static void	tcp_ack_timer(void *arg);
 static mblk_t	*tcp_ack_mp(tcp_t *tcp);
 static void	tcp_xmit_early_reset(char *str, mblk_t *mp,
@@ -18482,9 +18488,17 @@
 		 * depending on the availability of transmit resources at
 		 * the media layer.
 		 */
-		IP_DLS_ILL_TX(ill, mp);
-	} else {
-		putnext(ire->ire_stq, mp);
+		IP_DLS_ILL_TX(ill, ipha, mp);
+	} else {
+		ill_t *out_ill = (ill_t *)ire->ire_stq->q_ptr;
+		DTRACE_PROBE4(ip4__physical__out__start,
+		    ill_t *, NULL, ill_t *, out_ill,
+		    ipha_t *, ipha, mblk_t *, mp);
+		FW_HOOKS(ip4_physical_out_event, ipv4firewall_physical_out,
+		    MSG_FWCOOKED_OUT, NULL, out_ill, ipha, mp, mp);
+		DTRACE_PROBE1(ip4__physical__out__end, mblk_t *, mp);
+		if (mp != NULL)
+			putnext(ire->ire_stq, mp);
 	}
 	IRE_REFRELE(ire);
 }
@@ -19099,6 +19113,7 @@
 	int		pbuf_idx, pbuf_idx_nxt;
 	int		seg_len, len, spill, af;
 	boolean_t	add_buffer, zcopy, clusterwide;
+	boolean_t	buf_trunked = B_FALSE;
 	boolean_t	rconfirm = B_FALSE;
 	boolean_t	done = B_FALSE;
 	uint32_t	cksum;
@@ -19112,6 +19127,8 @@
 	uint16_t	*up;
 	int		err;
 	conn_t		*connp;
+	mblk_t		*mp, *mp1, *fw_mp_head = NULL;
+	uchar_t		*pld_start;
 
 #ifdef	_BIG_ENDIAN
 #define	IPVER(ip6h)	((((uint32_t *)ip6h)[0] >> 28) & 0x7)
@@ -20056,6 +20073,117 @@
 				}
 			}
 
+			if (af == AF_INET && HOOKS4_INTERESTED_PHYSICAL_OUT||
+			    af == AF_INET6 && HOOKS6_INTERESTED_PHYSICAL_OUT) {
+				/* build header(IP/TCP) mblk for this segment */
+				if ((mp = dupb(md_hbuf)) == NULL)
+					goto legacy_send;
+
+				mp->b_rptr = pkt_info->hdr_rptr;
+				mp->b_wptr = pkt_info->hdr_wptr;
+
+				/* build payload mblk for this segment */
+				if ((mp1 = dupb(*xmit_tail)) == NULL) {
+					freemsg(mp);
+					goto legacy_send;
+				}
+				mp1->b_wptr = md_pbuf->b_rptr + cur_pld_off;
+				mp1->b_rptr = mp1->b_wptr -
+				    tcp->tcp_last_sent_len;
+				linkb(mp, mp1);
+
+				pld_start = mp1->b_rptr;
+
+				if (af == AF_INET) {
+					DTRACE_PROBE4(
+					    ip4__physical__out__start,
+					    ill_t *, NULL,
+					    ill_t *, ill,
+					    ipha_t *, ipha,
+					    mblk_t *, mp);
+					FW_HOOKS(ip4_physical_out_event,
+					    ipv4firewall_physical_out,
+					    MSG_FWCOOKED_OUT, NULL, ill, ipha,
+					    mp, mp);
+					DTRACE_PROBE1(
+					    ip4__physical__out__end,
+					    mblk_t *, mp);
+				} else {
+					DTRACE_PROBE4(
+					    ip6__physical__out_start,
+					    ill_t *, NULL,
+					    ill_t *, ill,
+					    ip6_t *, ip6h,
+					    mblk_t *, mp);
+					FW_HOOKS6(ip6_physical_out_event,
+					    ipv6firewall_physical_out,
+					    MSG_FWCOOKED_OUT, NULL, ill, ip6h,
+					    mp, mp);
+					DTRACE_PROBE1(
+					    ip6__physical__out__end,
+					    mblk_t *, mp);
+				}
+
+				if (buf_trunked && mp != NULL) {
+					/*
+					 * Need to pass it to normal path.
+					 */
+					CALL_IP_WPUT(tcp->tcp_connp, q, mp);
+				} else if (mp == NULL ||
+				    mp->b_rptr != pkt_info->hdr_rptr ||
+				    mp->b_wptr != pkt_info->hdr_wptr ||
+				    (mp1 = mp->b_cont) == NULL ||
+				    mp1->b_rptr != pld_start ||
+				    mp1->b_wptr != pld_start +
+				    tcp->tcp_last_sent_len ||
+				    mp1->b_cont != NULL) {
+					/*
+					 * Need to pass all packets of this
+					 * buffer to normal path, either when
+					 * packet is blocked, or when boundary
+					 * of header buffer or payload buffer
+					 * has been changed by FW_HOOKS[6].
+					 */
+					buf_trunked = B_TRUE;
+					if (md_mp_head != NULL) {
+						err = (intptr_t)rmvb(md_mp_head,
+						    md_mp);
+						if (err == 0)
+							md_mp_head = NULL;
+					}
+
+					/* send down what we've got so far */
+					if (md_mp_head != NULL) {
+						tcp_multisend_data(tcp, ire,
+						    ill, md_mp_head, obsegs,
+						    obbytes, &rconfirm);
+					}
+					md_mp_head = NULL;
+
+					if (mp != NULL)
+						CALL_IP_WPUT(tcp->tcp_connp,
+						    q, mp);
+
+					mp1 = fw_mp_head;
+					do {
+						mp = mp1;
+						mp1 = mp1->b_next;
+						mp->b_next = NULL;
+						mp->b_prev = NULL;
+						CALL_IP_WPUT(tcp->tcp_connp,
+						    q, mp);
+					} while (mp1 != NULL);
+
+					fw_mp_head = NULL;
+				} else {
+					if (fw_mp_head == NULL)
+						fw_mp_head = mp;
+					else
+						fw_mp_head->b_prev->b_next = mp;
+					fw_mp_head->b_prev = mp;
+				}
+			}
+
 			/* advance header offset */
 			cur_hdr_off += hdr_frag_sz;
 
@@ -20098,12 +20226,26 @@
 			*tail_unsent = (int)MBLKL(*xmit_tail);
 			add_buffer = B_TRUE;
 		}
+
+		while (fw_mp_head) {
+			mp = fw_mp_head;
+			fw_mp_head = fw_mp_head->b_next;
+			mp->b_prev = mp->b_next = NULL;
+			freemsg(mp);
+		}
+		if (buf_trunked) {
+			TCP_STAT(tcp_mdt_discarded);
+			freeb(md_mp);
+			buf_trunked = B_FALSE;
+		}
 	} while (!done && *usable > 0 && num_burst_seg > 0 &&
 	    (tcp_mdt_chain || max_pld > 0));
 
-	/* send everything down */
-	tcp_multisend_data(tcp, ire, ill, md_mp_head, obsegs, obbytes,
-	    &rconfirm);
+	if (md_mp_head != NULL) {
+		/* send everything down */
+		tcp_multisend_data(tcp, ire, ill, md_mp_head, obsegs, obbytes,
+		    &rconfirm);
+	}
 
 #undef PREP_NEW_MULTIDATA
 #undef PREP_NEW_PBUF
@@ -21926,7 +22068,7 @@
  * be adjusted by *offset.  And after dupb(), the offset and the ending mblk
  * of the original mblk chain will be returned in *offset and *end_mp.
  */
-static mblk_t *
+mblk_t *
 tcp_xmit_mp(tcp_t *tcp, mblk_t *mp, int32_t max_to_send, int32_t *offset,
     mblk_t **end_mp, uint32_t seq, boolean_t sendall, uint32_t *seg_len,
     boolean_t rexmit)
--- a/usr/src/uts/common/inet/tcp/tcp_fusion.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/tcp/tcp_fusion.c	Fri Oct 20 16:37:58 2006 -0700
@@ -30,6 +30,7 @@
 #include <sys/strsun.h>
 #include <sys/strsubr.h>
 #include <sys/debug.h>
+#include <sys/sdt.h>
 #include <sys/cmn_err.h>
 #include <sys/tihdr.h>
 
@@ -463,6 +464,14 @@
 	uint_t max_unread;
 	boolean_t flow_stopped;
 	boolean_t urgent = (DB_TYPE(mp) != M_DATA);
+	mblk_t *mp1 = mp;
+	ill_t *ilp, *olp;
+	ipha_t *ipha;
+	ip6_t *ip6h;
+	tcph_t *tcph;
+	uint_t ip_hdr_len;
+	uint32_t seq;
+	uint32_t recv_size = send_size;
 
 	ASSERT(tcp->tcp_fused);
 	ASSERT(peer_tcp != NULL && peer_tcp->tcp_loopback_peer == tcp);
@@ -476,8 +485,7 @@
 	if (TCP_LOOPBACK_IP(tcp) || TCP_LOOPBACK_IP(peer_tcp) ||
 	    IPP_ENABLED(IPP_LOCAL_OUT|IPP_LOCAL_IN)) {
 		TCP_STAT(tcp_fusion_aborted);
-		tcp_unfuse(tcp);
-		return (B_FALSE);
+		goto unfuse;
 	}
 
 	if (send_size == 0) {
@@ -500,6 +508,93 @@
 		 */
 		TCP_FUSE_SYNCSTR_PLUG_DRAIN(peer_tcp);
 		tcp_fuse_output_urg(tcp, mp);
+
+		mp1 = mp->b_cont;
+	}
+
+	if (tcp->tcp_ipversion == IPV4_VERSION &&
+	    (HOOKS4_INTERESTED_LOOPBACK_IN ||
+	    HOOKS4_INTERESTED_LOOPBACK_OUT) ||
+	    tcp->tcp_ipversion == IPV6_VERSION &&
+	    (HOOKS6_INTERESTED_LOOPBACK_IN ||
+	    HOOKS6_INTERESTED_LOOPBACK_OUT)) {
+		/*
+		 * Build ip and tcp header to satisfy FW_HOOKS.
+		 * We only build it when any hook is present.
+		 */
+		if ((mp1 = tcp_xmit_mp(tcp, mp1, tcp->tcp_mss, NULL, NULL,
+		    tcp->tcp_snxt, B_TRUE, NULL, B_FALSE)) == NULL)
+			/* If tcp_xmit_mp fails, use regular path */
+			goto unfuse;
+
+		ASSERT(peer_tcp->tcp_connp->conn_ire_cache->ire_ipif != NULL);
+		olp = peer_tcp->tcp_connp->conn_ire_cache->ire_ipif->ipif_ill;
+		/* PFHooks: LOOPBACK_OUT */
+		if (tcp->tcp_ipversion == IPV4_VERSION) {
+			ipha = (ipha_t *)mp1->b_rptr;
+
+			DTRACE_PROBE4(ip4__loopback__out__start,
+			    ill_t *, NULL, ill_t *, olp,
+			    ipha_t *, ipha, mblk_t *, mp1);
+			FW_HOOKS(ip4_loopback_out_event,
+			    ipv4firewall_loopback_out, MSG_FWCOOKED_OUT, NULL,
+			    olp, ipha, mp1, mp1);
+			DTRACE_PROBE1(ip4__loopback__out__end, mblk_t *, mp1);
+		} else {
+			ip6h = (ip6_t *)mp1->b_rptr;
+
+			DTRACE_PROBE4(ip6__loopback__out__start,
+			    ill_t *, NULL, ill_t *, olp,
+			    ip6_t *, ip6h, mblk_t *, mp1);
+			FW_HOOKS6(ip6_loopback_out_event,
+			    ipv6firewall_loopback_out, MSG_FWCOOKED_OUT, NULL,
+			    olp, ip6h, mp1, mp1);
+			DTRACE_PROBE1(ip6__loopback__out__end, mblk_t *, mp1);
+		}
+		if (mp1 == NULL)
+			goto unfuse;
+
+
+		/* PFHooks: LOOPBACK_IN */
+		ASSERT(tcp->tcp_connp->conn_ire_cache->ire_ipif != NULL);
+		ilp = tcp->tcp_connp->conn_ire_cache->ire_ipif->ipif_ill;
+
+		if (tcp->tcp_ipversion == IPV4_VERSION) {
+			DTRACE_PROBE4(ip4__loopback__in__start,
+			    ill_t *, ilp, ill_t *, NULL,
+			    ipha_t *, ipha, mblk_t *, mp1);
+			FW_HOOKS(ip4_loopback_in_event,
+			    ipv4firewall_loopback_in, MSG_FWCOOKED_IN, ilp,
+			    NULL, ipha, mp1, mp1);
+			DTRACE_PROBE1(ip4__loopback__in__end, mblk_t *, mp1);
+			if (mp1 == NULL)
+				goto unfuse;
+
+			ip_hdr_len = IPH_HDR_LENGTH(ipha);
+		} else {
+			DTRACE_PROBE4(ip6__loopback__in__start,
+			    ill_t *, ilp, ill_t *, NULL,
+			    ip6_t *, ip6h, mblk_t *, mp1);
+			FW_HOOKS6(ip6_loopback_in_event,
+			    ipv6firewall_loopback_in, MSG_FWCOOKED_IN, ilp,
+			    NULL, ip6h, mp1, mp1);
+			DTRACE_PROBE1(ip6__loopback__in__end, mblk_t *, mp1);
+			if (mp1 == NULL)
+				goto unfuse;
+
+			ip_hdr_len = ip_hdr_length_v6(mp1, ip6h);
+		}
+
+		/* Data length might be changed by FW_HOOKS */
+		tcph = (tcph_t *)&mp1->b_rptr[ip_hdr_len];
+		seq = ABE32_TO_U32(tcph->th_seq);
+		recv_size += seq - tcp->tcp_snxt;
+
+		/*
+		 * The message duplicated by tcp_xmit_mp is freed.
+		 * Note: the original message passed in remains unchanged.
+		 */
+		freemsg(mp1);
 	}
 
 	mutex_enter(&peer_tcp->tcp_fuse_lock);
@@ -528,10 +623,10 @@
 	 * Enqueue data into the peer's receive list; we may or may not
 	 * drain the contents depending on the conditions below.
 	 */
-	tcp_rcv_enqueue(peer_tcp, mp, send_size);
+	tcp_rcv_enqueue(peer_tcp, mp, recv_size);
 
 	/* In case it wrapped around and also to keep it constant */
-	peer_tcp->tcp_rwnd += send_size;
+	peer_tcp->tcp_rwnd += recv_size;
 
 	/*
 	 * Exercise flow-control when needed; we will get back-enabled
@@ -574,7 +669,7 @@
 	/* Need to adjust the following SNMP MIB-related variables */
 	tcp->tcp_snxt += send_size;
 	tcp->tcp_suna = tcp->tcp_snxt;
-	peer_tcp->tcp_rnxt += send_size;
+	peer_tcp->tcp_rnxt += recv_size;
 	peer_tcp->tcp_rack = peer_tcp->tcp_rnxt;
 
 	BUMP_MIB(&tcp_mib, tcpOutDataSegs);
@@ -620,6 +715,9 @@
 		}
 	}
 	return (B_TRUE);
+unfuse:
+	tcp_unfuse(tcp);
+	return (B_FALSE);
 }
 
 /*
--- a/usr/src/uts/common/inet/udp/udp.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/inet/udp/udp.c	Fri Oct 20 16:37:58 2006 -0700
@@ -53,6 +53,7 @@
 #include <sys/socket.h>
 #include <sys/sockio.h>
 #include <sys/vtrace.h>
+#include <sys/sdt.h>
 #include <sys/debug.h>
 #include <sys/isa_defs.h>
 #include <sys/random.h>
@@ -6722,9 +6723,16 @@
 		 * depending on the availability of transmit resources at
 		 * the media layer.
 		 */
-		IP_DLS_ILL_TX(ill, mp);
+		IP_DLS_ILL_TX(ill, ipha, mp);
 	} else {
-		putnext(ire->ire_stq, mp);
+		DTRACE_PROBE4(ip4__physical__out__start,
+		    ill_t *, NULL, ill_t *, ill,
+		    ipha_t *, ipha, mblk_t *, mp);
+		FW_HOOKS(ip4_physical_out_event, ipv4firewall_physical_out,
+		    MSG_FWCOOKED_OUT, NULL, ill, ipha, mp, mp);
+		DTRACE_PROBE1(ip4__physical__out__end, mblk_t *, mp);
+		if (mp != NULL)
+			putnext(ire->ire_stq, mp);
 	}
 
 	if (ipif != NULL)
--- a/usr/src/uts/common/io/bge/bge_send.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/io/bge/bge_send.c	Fri Oct 20 16:37:58 2006 -0700
@@ -409,23 +409,12 @@
 
 	if (ehp->ether_tpid == htons(ETHERTYPE_VLAN)) {
 		if (MBLKL(mp) < sizeof (struct ether_vlan_header)) {
-			uint32_t pflags;
-
-			/*
-			 * Need to preserve checksum flags across pullup.
-			 */
-			hcksum_retrieve(mp, NULL, NULL, NULL, NULL, NULL,
-			    NULL, &pflags);
-
 			if (!pullupmsg(mp,
 			    sizeof (struct ether_vlan_header))) {
 				BGE_DEBUG(("bge_send: pullup failure"));
 				bgep->resched_needed = B_TRUE;
 				return (B_FALSE);
 			}
-
-			(void) hcksum_assoc(mp, NULL, NULL, NULL, NULL, NULL,
-			    NULL, pflags, KM_NOSLEEP);
 		}
 
 		ehp = (struct ether_vlan_header *)mp->b_rptr;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/io/hook.c	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,685 @@
+/*
+ * 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 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/kmem.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/modctl.h>
+#include <sys/hook_impl.h>
+#include <sys/sdt.h>
+
+/*
+ * This file provides kernel hook framework.
+ */
+
+static struct modldrv modlmisc = {
+	&mod_miscops,				/* drv_modops */
+	"Hooks Interface v1.0",			/* drv_linkinfo */
+};
+
+static struct modlinkage modlinkage = {
+	MODREV_1,				/* ml_rev */
+	&modlmisc,				/* ml_linkage */
+	NULL
+};
+
+/*
+ * Hook internal functions
+ */
+static hook_int_t *hook_copy(hook_t *src);
+static hook_event_int_t *hook_event_checkdup(hook_event_t *he);
+static hook_event_int_t *hook_event_copy(hook_event_t *src);
+static hook_event_int_t *hook_event_find(hook_family_int_t *hfi, char *event);
+static void hook_event_free(hook_event_int_t *hei);
+static hook_family_int_t *hook_family_copy(hook_family_t *src);
+static hook_family_int_t *hook_family_find(char *family);
+static void hook_family_free(hook_family_int_t *hfi);
+static hook_int_t *hook_find(hook_event_int_t *hei, hook_t *h);
+static void hook_free(hook_int_t *hi);
+static void hook_init(void);
+
+static cvwaitlock_t familylock;			/* global lock */
+static hook_family_int_head_t familylist;	/* family list head */
+
+/*
+ * Module entry points.
+ */
+int
+_init(void)
+{
+	hook_init();
+	return (mod_install(&modlinkage));
+}
+
+
+int
+_fini(void)
+{
+	return (mod_remove(&modlinkage));
+}
+
+
+int
+_info(struct modinfo *modinfop)
+{
+	return (mod_info(&modlinkage, modinfop));
+}
+
+
+/*
+ * Function:	hook_init
+ * Returns:	None
+ * Parameters:	None
+ *
+ * Initialize hooks
+ */
+static void
+hook_init(void)
+{
+	CVW_INIT(&familylock);
+	SLIST_INIT(&familylist);
+}
+
+
+/*
+ * Function:	hook_run
+ * Returns:	int - return value according to callback func
+ * Parameters:	token(I) - event pointer
+ *		info(I) - message
+ *
+ * Run hooks for specific provider.  The hooks registered are stepped through
+ * until either the end of the list is reached or a hook function returns a
+ * non-zero value.  If a non-zero value is returned from a hook function, we
+ * return that value back to our caller.  By design, a hook function can be
+ * called more than once, simultaneously.
+ */
+int
+hook_run(hook_event_token_t token, hook_data_t info)
+{
+	hook_int_t *hi;
+	hook_event_int_t *hei;
+	int rval = 0;
+
+	ASSERT(token != NULL);
+
+	hei = (hook_event_int_t *)token;
+	DTRACE_PROBE2(hook__run__start,
+	    hook_event_token_t, token,
+	    hook_data_t, info);
+
+	/* Hold global read lock to ensure event will not be deleted */
+	CVW_ENTER_READ(&familylock);
+
+	/* Hold event read lock to ensure hook will not be changed */
+	CVW_ENTER_READ(&hei->hei_lock);
+
+	TAILQ_FOREACH(hi, &hei->hei_head, hi_entry) {
+		ASSERT(hi->hi_hook.h_func != NULL);
+		DTRACE_PROBE3(hook__func__start,
+		    hook_event_token_t, token,
+		    hook_data_t, info,
+		    hook_int_t *, hi);
+		rval = (*hi->hi_hook.h_func)(token, info);
+		DTRACE_PROBE4(hook__func__end,
+		    hook_event_token_t, token,
+		    hook_data_t, info,
+		    hook_int_t *, hi,
+		    int, rval);
+		if (rval != 0)
+			break;
+	}
+
+	CVW_EXIT_READ(&hei->hei_lock);
+	CVW_EXIT_READ(&familylock);
+
+	DTRACE_PROBE3(hook__run__end,
+	    hook_event_token_t, token,
+	    hook_data_t, info,
+	    hook_int_t *, hi);
+
+	return (rval);
+}
+
+
+/*
+ * Function:	hook_family_add
+ * Returns:	internal family pointer - NULL = Fail
+ * Parameters:	hf(I) - family pointer
+ *
+ * Add new family to family list
+ */
+hook_family_int_t *
+hook_family_add(hook_family_t *hf)
+{
+	hook_family_int_t *hfi, *new;
+
+	ASSERT(hf != NULL);
+	ASSERT(hf->hf_name != NULL);
+
+	new = hook_family_copy(hf);
+	if (new == NULL)
+		return (NULL);
+
+	CVW_ENTER_WRITE(&familylock);
+
+	/* search family list */
+	hfi = hook_family_find(hf->hf_name);
+	if (hfi != NULL) {
+		CVW_EXIT_WRITE(&familylock);
+		hook_family_free(new);
+		return (NULL);
+	}
+
+	/* Add to family list head */
+	SLIST_INSERT_HEAD(&familylist, new, hfi_entry);
+
+	CVW_EXIT_WRITE(&familylock);
+	return (new);
+}
+
+
+/*
+ * Function:	hook_family_remove
+ * Returns:	int - 0 = Succ, Else = Fail
+ * Parameters:	hfi(I) - internal family pointer
+ *
+ * Remove family from family list
+ */
+int
+hook_family_remove(hook_family_int_t *hfi)
+{
+
+	ASSERT(hfi != NULL);
+
+	CVW_ENTER_WRITE(&familylock);
+
+	/* Check if there are events  */
+	if (!SLIST_EMPTY(&hfi->hfi_head)) {
+		CVW_EXIT_WRITE(&familylock);
+		return (EBUSY);
+	}
+
+	/* Remove from family list */
+	SLIST_REMOVE(&familylist, hfi, hook_family_int, hfi_entry);
+
+	CVW_EXIT_WRITE(&familylock);
+	hook_family_free(hfi);
+
+	return (0);
+}
+
+
+/*
+ * Function:	hook_family_copy
+ * Returns:	internal family pointer - NULL = Failed
+ * Parameters:	src(I) - family pointer
+ *
+ * Allocate internal family block and duplicate incoming family
+ * No locks should be held across this function as it may sleep.
+ */
+static hook_family_int_t *
+hook_family_copy(hook_family_t *src)
+{
+	hook_family_int_t *new;
+	hook_family_t *dst;
+
+	ASSERT(src != NULL);
+	ASSERT(src->hf_name != NULL);
+
+	new = (hook_family_int_t *)kmem_zalloc(sizeof (*new), KM_SLEEP);
+
+	/* Copy body */
+	SLIST_INIT(&new->hfi_head);
+	dst = &new->hfi_family;
+	*dst = *src;
+
+	/* Copy name */
+	dst->hf_name = (char *)kmem_alloc(strlen(src->hf_name) + 1, KM_SLEEP);
+	(void) strcpy(dst->hf_name, src->hf_name);
+
+	return (new);
+}
+
+
+/*
+ * Function:	hook_family_find
+ * Returns:	internal family pointer - NULL = Not match
+ * Parameters:	family(I) - family name string
+ *
+ * Search family list with family name
+ * 	A lock on familylock must be held when called.
+ */
+static hook_family_int_t *
+hook_family_find(char *family)
+{
+	hook_family_int_t *hfi = NULL;
+
+	ASSERT(family != NULL);
+
+	SLIST_FOREACH(hfi, &familylist, hfi_entry) {
+		if (strcmp(hfi->hfi_family.hf_name, family) == 0)
+			break;
+	}
+	return (hfi);
+}
+
+
+/*
+ * Function:	hook_family_free
+ * Returns:	None
+ * Parameters:	hfi(I) - internal family pointer
+ *
+ * Free alloc memory for family
+ */
+static void
+hook_family_free(hook_family_int_t *hfi)
+{
+	ASSERT(hfi != NULL);
+
+	/* Free name space */
+	if (hfi->hfi_family.hf_name != NULL) {
+		kmem_free(hfi->hfi_family.hf_name,
+		    strlen(hfi->hfi_family.hf_name) + 1);
+	}
+
+	/* Free container */
+	kmem_free(hfi, sizeof (*hfi));
+}
+
+
+/*
+ * Function:	hook_event_add
+ * Returns:	internal event pointer - NULL = Fail
+ * Parameters:	hfi(I) - internal family pointer
+ *		he(I) - event pointer
+ *
+ * Add new event to event list on specific family.
+ * This function can fail to return successfully if (1) it cannot allocate
+ * enough memory for its own internal data structures, (2) the event has
+ * already been registered (for any hook family.)
+ */
+hook_event_int_t *
+hook_event_add(hook_family_int_t *hfi, hook_event_t *he)
+{
+	hook_event_int_t *hei, *new;
+
+	ASSERT(hfi != NULL);
+	ASSERT(he != NULL);
+	ASSERT(he->he_name != NULL);
+
+	new = hook_event_copy(he);
+	if (new == NULL)
+		return (NULL);
+
+	CVW_ENTER_WRITE(&familylock);
+
+	/* Check whether this event pointer is already registered */
+	hei = hook_event_checkdup(he);
+	if (hei != NULL) {
+		CVW_EXIT_WRITE(&familylock);
+		hook_event_free(new);
+		return (NULL);
+	}
+
+	/* Add to event list head */
+	SLIST_INSERT_HEAD(&hfi->hfi_head, new, hei_entry);
+
+	CVW_EXIT_WRITE(&familylock);
+	return (new);
+}
+
+
+/*
+ * Function:	hook_event_remove
+ * Returns:	int - 0 = Succ, Else = Fail
+ * Parameters:	hfi(I) - internal family pointer
+ *		he(I) - event pointer
+ *
+ * Remove event from event list on specific family
+ */
+int
+hook_event_remove(hook_family_int_t *hfi, hook_event_t *he)
+{
+	hook_event_int_t *hei;
+
+	ASSERT(hfi != NULL);
+	ASSERT(he != NULL);
+
+	CVW_ENTER_WRITE(&familylock);
+
+	hei = hook_event_find(hfi, he->he_name);
+	if (hei == NULL) {
+		CVW_EXIT_WRITE(&familylock);
+		return (ENXIO);
+	}
+
+	/* Check if there are registered hooks for this event */
+	if (!TAILQ_EMPTY(&hei->hei_head)) {
+		CVW_EXIT_WRITE(&familylock);
+		return (EBUSY);
+	}
+
+	/* Remove from event list */
+	SLIST_REMOVE(&hfi->hfi_head, hei, hook_event_int, hei_entry);
+
+	CVW_EXIT_WRITE(&familylock);
+	hook_event_free(hei);
+
+	return (0);
+}
+
+
+/*
+ * Function:    hook_event_checkdup
+ * Returns:     internal event pointer - NULL = Not match
+ * Parameters:  he(I) - event pointer
+ *
+ * Search whole list with event pointer
+ *      A lock on familylock must be held when called.
+ */
+static hook_event_int_t *
+hook_event_checkdup(hook_event_t *he)
+{
+	hook_family_int_t *hfi;
+	hook_event_int_t *hei;
+
+	ASSERT(he != NULL);
+
+	SLIST_FOREACH(hfi, &familylist, hfi_entry) {
+		SLIST_FOREACH(hei, &hfi->hfi_head, hei_entry) {
+			if (hei->hei_event == he)
+				return (hei);
+		}
+	}
+
+	return (NULL);
+}
+
+
+/*
+ * Function:	hook_event_copy
+ * Returns:	internal event pointer - NULL = Failed
+ * Parameters:	src(I) - event pointer
+ *
+ * Allocate internal event block and duplicate incoming event
+ * No locks should be held across this function as it may sleep.
+ */
+static hook_event_int_t *
+hook_event_copy(hook_event_t *src)
+{
+	hook_event_int_t *new;
+
+	ASSERT(src != NULL);
+	ASSERT(src->he_name != NULL);
+
+	new = (hook_event_int_t *)kmem_zalloc(sizeof (*new), KM_SLEEP);
+
+	/* Copy body */
+	TAILQ_INIT(&new->hei_head);
+	new->hei_event = src;
+
+	return (new);
+}
+
+
+/*
+ * Function:	hook_event_find
+ * Returns:	internal event pointer - NULL = Not match
+ * Parameters:	hfi(I) - internal family pointer
+ *		event(I) - event name string
+ *
+ * Search event list with event name
+ * 	A lock on familylock must be held when called.
+ */
+static hook_event_int_t *
+hook_event_find(hook_family_int_t *hfi, char *event)
+{
+	hook_event_int_t *hei = NULL;
+
+	ASSERT(hfi != NULL);
+	ASSERT(event != NULL);
+
+	SLIST_FOREACH(hei, &hfi->hfi_head, hei_entry) {
+		if (strcmp(hei->hei_event->he_name, event) == 0)
+			break;
+	}
+	return (hei);
+}
+
+
+/*
+ * Function:	hook_event_free
+ * Returns:	None
+ * Parameters:	hei(I) - internal event pointer
+ *
+ * Free alloc memory for event
+ */
+static void
+hook_event_free(hook_event_int_t *hei)
+{
+	ASSERT(hei != NULL);
+
+	/* Free container */
+	kmem_free(hei, sizeof (*hei));
+}
+
+
+/*
+ * Function:	hook_register
+ * Returns:	int- 0 = Succ, Else = Fail
+ * Parameters:	hfi(I) - internal family pointer
+ *		event(I) - event name string
+ *		h(I) - hook pointer
+ *
+ * Add new hook to hook list on spefic family, event
+ */
+int
+hook_register(hook_family_int_t *hfi, char *event, hook_t *h)
+{
+	hook_event_int_t *hei;
+	hook_int_t *hi, *new;
+
+	ASSERT(hfi != NULL);
+	ASSERT(event != NULL);
+	ASSERT(h != NULL);
+
+	/* Alloc hook_int_t and copy hook */
+	new = hook_copy(h);
+	if (new == NULL)
+		return (ENOMEM);
+
+	/*
+	 * Since hook add/remove only impact event, so it is unnecessary
+	 * to hold global family write lock. Just get read lock here to
+	 * ensure event will not be removed when doing hooks operation
+	 */
+	CVW_ENTER_READ(&familylock);
+
+	hei = hook_event_find(hfi, event);
+	if (hei == NULL) {
+		CVW_EXIT_READ(&familylock);
+		hook_free(new);
+		return (ENXIO);
+	}
+
+	CVW_ENTER_WRITE(&hei->hei_lock);
+
+	/* Multiple hooks are only allowed for read-only events. */
+	if (((hei->hei_event->he_flags & HOOK_RDONLY) == 0) &&
+	    (!TAILQ_EMPTY(&hei->hei_head))) {
+		CVW_EXIT_WRITE(&hei->hei_lock);
+		CVW_EXIT_READ(&familylock);
+		hook_free(new);
+		return (EEXIST);
+	}
+
+	hi = hook_find(hei, h);
+	if (hi != NULL) {
+		CVW_EXIT_WRITE(&hei->hei_lock);
+		CVW_EXIT_READ(&familylock);
+		hook_free(new);
+		return (EEXIST);
+	}
+
+	/* Add to hook list head */
+	TAILQ_INSERT_HEAD(&hei->hei_head, new, hi_entry);
+	hei->hei_event->he_interested = B_TRUE;
+
+	CVW_EXIT_WRITE(&hei->hei_lock);
+	CVW_EXIT_READ(&familylock);
+	return (0);
+}
+
+
+/*
+ * Function:	hook_unregister
+ * Returns:	int - 0 = Succ, Else = Fail
+ * Parameters:	hfi(I) - internal family pointer
+ *		event(I) - event name string
+ *		h(I) - hook pointer
+ *
+ * Remove hook from hook list on specific family, event
+ */
+int
+hook_unregister(hook_family_int_t *hfi, char *event, hook_t *h)
+{
+	hook_event_int_t *hei;
+	hook_int_t *hi;
+
+	ASSERT(hfi != NULL);
+	ASSERT(h != NULL);
+
+	CVW_ENTER_READ(&familylock);
+
+	hei = hook_event_find(hfi, event);
+	if (hei == NULL) {
+		CVW_EXIT_READ(&familylock);
+		return (ENXIO);
+	}
+
+	/* Hold write lock for event */
+	CVW_ENTER_WRITE(&hei->hei_lock);
+
+	hi = hook_find(hei, h);
+	if (hi == NULL) {
+		CVW_EXIT_WRITE(&hei->hei_lock);
+		CVW_EXIT_READ(&familylock);
+		return (ENXIO);
+	}
+
+	/* Remove from hook list */
+	TAILQ_REMOVE(&hei->hei_head, hi, hi_entry);
+	if (TAILQ_EMPTY(&hei->hei_head)) {
+		hei->hei_event->he_interested = B_FALSE;
+	}
+
+	CVW_EXIT_WRITE(&hei->hei_lock);
+	CVW_EXIT_READ(&familylock);
+
+	hook_free(hi);
+	return (0);
+}
+
+
+/*
+ * Function:	hook_find
+ * Returns:	internal hook pointer - NULL = Not match
+ * Parameters:	hei(I) - internal event pointer
+ *		h(I) - hook pointer
+ *
+ * Search hook list
+ * 	A lock on familylock must be held when called.
+ */
+static hook_int_t *
+hook_find(hook_event_int_t *hei, hook_t *h)
+{
+	hook_int_t *hi;
+
+	ASSERT(hei != NULL);
+	ASSERT(h != NULL);
+
+	TAILQ_FOREACH(hi, &hei->hei_head, hi_entry) {
+		if (strcmp(hi->hi_hook.h_name, h->h_name) == 0)
+			break;
+	}
+	return (hi);
+}
+
+
+/*
+ * Function:	hook_copy
+ * Returns:	internal hook pointer - NULL = Failed
+ * Parameters:	src(I) - hook pointer
+ *
+ * Allocate internal hook block and duplicate incoming hook.
+ * No locks should be held across this function as it may sleep.
+ */
+static hook_int_t *
+hook_copy(hook_t *src)
+{
+	hook_int_t *new;
+	hook_t *dst;
+
+	ASSERT(src != NULL);
+	ASSERT(src->h_name != NULL);
+
+	new = (hook_int_t *)kmem_zalloc(sizeof (*new), KM_SLEEP);
+
+	/* Copy body */
+	dst = &new->hi_hook;
+	*dst = *src;
+
+	/* Copy name */
+	dst->h_name = (char *)kmem_alloc(strlen(src->h_name) + 1, KM_SLEEP);
+	(void) strcpy(dst->h_name, src->h_name);
+
+	return (new);
+}
+
+/*
+ * Function:	hook_free
+ * Returns:	None
+ * Parameters:	hi(I) - internal hook pointer
+ *
+ * Free alloc memory for hook
+ */
+static void
+hook_free(hook_int_t *hi)
+{
+	ASSERT(hi != NULL);
+
+	/* Free name space */
+	if (hi->hi_hook.h_name != NULL) {
+		kmem_free(hi->hi_hook.h_name, strlen(hi->hi_hook.h_name) + 1);
+	}
+
+	/* Free container */
+	kmem_free(hi, sizeof (*hi));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/io/neti.c	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,509 @@
+/*
+ * 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 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/param.h>
+#include <sys/atomic.h>
+#include <sys/kmem.h>
+#include <sys/rwlock.h>
+#include <sys/errno.h>
+#include <sys/queue.h>
+#include <inet/common.h>
+#include <inet/led.h>
+#include <inet/ip.h>
+#include <sys/modctl.h>
+#include <sys/neti.h>
+
+
+static krwlock_t netlock;
+static LIST_HEAD(netd_listhead, net_data) netd_head; /* list of net_data_t */
+
+static void net_init();
+static net_data_t net_find(const char *protocol);
+
+/*
+ * Module linkage information for the kernel.
+ */
+static struct modldrv modlmisc = {
+	&mod_miscops,		/* drv_modops */
+	"netinfo module 1.0",	/* drv_linkinfo */
+};
+
+static struct modlinkage modlinkage = {
+	MODREV_1,		/* ml_rev */
+	&modlmisc,		/* ml_linkage */
+	NULL
+};
+
+/*
+ * Module entry points.
+ */
+int
+_init(void)
+{
+	net_init();
+	return (mod_install(&modlinkage));
+}
+
+
+int
+_fini(void)
+{
+
+	return (mod_remove(&modlinkage));
+}
+
+
+int
+_info(struct modinfo *modinfop)
+{
+
+	return (mod_info(&modlinkage, modinfop));
+}
+
+
+static void
+net_init()
+{
+
+	rw_init(&netlock, NULL, RW_DRIVER, NULL);
+	LIST_INIT(&netd_head);
+}
+
+
+static net_data_t
+net_find(const char *protocol)
+{
+	struct net_data *n;
+
+	ASSERT(protocol != NULL);
+
+	LIST_FOREACH(n, &netd_head, netd_list) {
+		ASSERT(n->netd_info.neti_protocol != NULL);
+		if (strcmp(n->netd_info.neti_protocol, protocol) == 0) {
+			break;
+		}
+	}
+
+	return (n);
+}
+
+
+net_data_t
+net_register(const net_info_t *info)
+{
+	struct net_data *n, *new;
+
+	ASSERT(info != NULL);
+
+	new = kmem_alloc(sizeof (*new), KM_SLEEP);
+	new->netd_refcnt = 0;
+	new->netd_hooks = NULL;
+	new->netd_info = *info;
+
+	rw_enter(&netlock, RW_WRITER);
+	n = net_find(info->neti_protocol);
+	if (n != NULL) {
+		rw_exit(&netlock);
+		kmem_free(new, sizeof (*new));
+		return (NULL);
+	}
+
+	if (LIST_EMPTY(&netd_head))
+		LIST_INSERT_HEAD(&netd_head, new, netd_list);
+	else
+		LIST_INSERT_AFTER(LIST_FIRST(&netd_head), new, netd_list);
+
+	rw_exit(&netlock);
+	return (new);
+}
+
+
+int
+net_unregister(net_data_t info)
+{
+
+	ASSERT(info != NULL);
+
+	rw_enter(&netlock, RW_WRITER);
+	if (info->netd_refcnt != 0) {
+		rw_exit(&netlock);
+		return (EBUSY);
+	}
+
+	LIST_REMOVE(info, netd_list);
+
+	rw_exit(&netlock);
+
+	kmem_free(info, sizeof (struct net_data));
+	return (0);
+}
+
+
+net_data_t
+net_lookup(const char *protocol)
+{
+	struct net_data *n;
+
+	ASSERT(protocol != NULL);
+
+	rw_enter(&netlock, RW_READER);
+	n = net_find(protocol);
+	if (n != NULL)
+		atomic_add_32((uint_t *)&n->netd_refcnt, 1);
+	rw_exit(&netlock);
+	return (n);
+}
+
+/*
+ * Note: the man page specifies "returns -1 if the value passed in is unknown
+ * to this framework".  We are not doing a lookup in this function, just a
+ * simply add to the netd_refcnt of the net_data_t passed in, so -1 is never a
+ * return value.
+ */
+int
+net_release(net_data_t info)
+{
+	ASSERT(info != NULL);
+
+	rw_enter(&netlock, RW_READER);
+	ASSERT(info->netd_refcnt > 0);
+	atomic_add_32((uint_t *)&info->netd_refcnt, -1);
+
+	/* net_release has been called too many times */
+	if (info->netd_refcnt < 0) {
+		rw_exit(&netlock);
+		return (1);
+	}
+	rw_exit(&netlock);
+	return (0);
+}
+
+
+net_data_t
+net_walk(net_data_t info)
+{
+	struct net_data *n = NULL;
+	boolean_t found = B_FALSE;
+
+	if (info == NULL)
+		found = B_TRUE;
+
+	rw_enter(&netlock, RW_READER);
+	LIST_FOREACH(n, &netd_head, netd_list) {
+		if (found)
+			break;
+		if (n == info)
+			found = B_TRUE;
+	}
+
+	if (info != NULL) {
+		ASSERT(info->netd_refcnt > 0);
+		atomic_add_32((uint_t *)&info->netd_refcnt, -1);
+	}
+	if (n != NULL)
+		atomic_add_32((uint_t *)&n->netd_refcnt, 1);
+
+	rw_exit(&netlock);
+	return (n);
+}
+
+
+/*
+ * Public accessor functions
+ */
+int
+net_getifname(net_data_t info, phy_if_t phy_ifdata,
+    char *buffer, const size_t buflen)
+{
+
+	ASSERT(info != NULL);
+
+	return (info->netd_info.neti_getifname(phy_ifdata, buffer, buflen));
+}
+
+
+int
+net_getmtu(net_data_t info, phy_if_t phy_ifdata, lif_if_t ifdata)
+{
+
+	ASSERT(info != NULL);
+
+	return (info->netd_info.neti_getmtu(phy_ifdata, ifdata));
+}
+
+
+int
+net_getpmtuenabled(net_data_t info)
+{
+
+	ASSERT(info != NULL);
+
+	return (info->netd_info.neti_getpmtuenabled());
+}
+
+
+int
+net_getlifaddr(net_data_t info, phy_if_t phy_ifdata, lif_if_t ifdata,
+    int nelem, net_ifaddr_t type[], void *storage)
+{
+
+	ASSERT(info != NULL);
+
+	return (info->netd_info.neti_getlifaddr(phy_ifdata, ifdata,
+	    nelem, type, storage));
+}
+
+
+phy_if_t
+net_phygetnext(net_data_t info, phy_if_t phy_ifdata)
+{
+
+	ASSERT(info != NULL);
+
+	return (info->netd_info.neti_phygetnext(phy_ifdata));
+}
+
+
+phy_if_t
+net_phylookup(net_data_t info, const char *name)
+{
+
+	ASSERT(info != NULL);
+
+	return (info->netd_info.neti_phylookup(name));
+}
+
+
+lif_if_t
+net_lifgetnext(net_data_t info, phy_if_t ifidx, lif_if_t ifdata)
+{
+
+	ASSERT(info != NULL);
+
+	return (info->netd_info.neti_lifgetnext(ifidx, ifdata));
+}
+
+
+int
+net_inject(net_data_t info, inject_t style, net_inject_t *packet)
+{
+
+	ASSERT(info != NULL);
+
+	return (info->netd_info.neti_inject(style, packet));
+}
+
+
+phy_if_t
+net_routeto(net_data_t info, struct sockaddr *address)
+{
+
+	ASSERT(info != NULL);
+
+	return (info->netd_info.neti_routeto(address));
+}
+
+
+int
+net_ispartialchecksum(net_data_t info, mblk_t *mp)
+{
+
+	ASSERT(info != NULL);
+	ASSERT(mp != NULL);
+
+	return (info->netd_info.neti_ispartialchecksum(mp));
+}
+
+
+int
+net_isvalidchecksum(net_data_t info, mblk_t *mp)
+{
+
+	ASSERT(info != NULL);
+	ASSERT(mp != NULL);
+
+	return (info->netd_info.neti_isvalidchecksum(mp));
+}
+
+
+/*
+ * Hooks related functions
+ */
+
+/*
+ * Function:	net_register_family
+ * Returns:	int - 0 = Succ, Else = Fail
+ * Parameters:	info(I) - protocol
+ *		hf(I) - family pointer
+ *
+ * Call hook_family_add to register family
+ */
+int
+net_register_family(net_data_t info, hook_family_t *hf)
+{
+	hook_family_int_t *hfi;
+
+	ASSERT(info != NULL);
+	ASSERT(hf != NULL);
+
+	if (info->netd_hooks != NULL)
+		return (EEXIST);
+
+	hfi = hook_family_add(hf);
+	if (hfi == NULL)
+		return (EEXIST);
+
+	info->netd_hooks = hfi;
+	return (0);
+}
+
+
+/*
+ * Function:	net_unregister_family
+ * Returns:	int - transparent value, explained by caller
+ * Parameters:	info(I) - protocol
+ *		hf(I) - family pointer
+ *
+ * Call hook_family_remove to unregister family
+ */
+int
+net_unregister_family(net_data_t info, hook_family_t *hf)
+{
+	int ret;
+
+	ASSERT(info != NULL);
+	ASSERT(hf != NULL);
+
+	if (info->netd_hooks == NULL)
+		return (ENXIO);
+
+	if (strcmp(info->netd_hooks->hfi_family.hf_name,
+	    hf->hf_name) != 0)
+		return (EINVAL);
+
+	ret = hook_family_remove(info->netd_hooks);
+	if (ret == 0)
+		info->netd_hooks = NULL;
+
+	return (ret);
+}
+
+
+/*
+ * Function:	net_register_event
+ * Returns:	internal event pointer - NULL = Fail
+ * Parameters:	info(I) - protocol
+ *		he(I) - event pointer
+ *
+ * Call hook_event_add to register event on specific family
+ * 	Internal event pointer is returned so caller can get
+ * 	handle to run hooks
+ */
+hook_event_token_t
+net_register_event(net_data_t info, hook_event_t *he)
+{
+	hook_event_int_t *hei;
+
+	ASSERT(info != NULL);
+	ASSERT(he != NULL);
+
+	if (info->netd_hooks == NULL)
+		return (NULL);
+
+	hei = hook_event_add(info->netd_hooks, he);
+	return ((hook_event_token_t)hei);
+}
+
+
+/*
+ * Function:	net_unregister_event
+ * Returns:	int - transparent value, explained by caller
+ * Parameters:	info(I) - protocol
+ *		he(I) - event pointer
+ *
+ * Call hook_event_remove to unregister event on specific family
+ */
+int
+net_unregister_event(net_data_t info, hook_event_t *he)
+{
+
+	ASSERT(info != NULL);
+	ASSERT(he != NULL);
+
+	if (info->netd_hooks == NULL)
+		return (ENXIO);
+
+	return (hook_event_remove(info->netd_hooks, he));
+}
+
+
+/*
+ * Function:	net_register_hook
+ * Returns:	int - transparent value, explained by caller
+ * Parameters:	info(I) - protocol
+ *		event(I) - event name
+ *		h(I) - hook pointer
+ *
+ * Call hook_register to add hook on specific family/event
+ */
+int
+net_register_hook(net_data_t info, char *event, hook_t *h)
+{
+
+	ASSERT(info != NULL);
+	ASSERT(event != NULL);
+	ASSERT(h != NULL);
+
+	if (info->netd_hooks == NULL)
+		return (ENXIO);
+
+	return (hook_register(info->netd_hooks, event, h));
+}
+
+
+/*
+ * Function:	net_unregister_hook
+ * Returns:	int - transparent value, explained by caller
+ * Parameters:	info(I) - protocol
+ *		event(I) - event name
+ *		h(I) - hook pointer
+ *
+ * Call hook_unregister to remove hook on specific family/event
+ */
+int
+net_unregister_hook(net_data_t info, char *event, hook_t *h)
+{
+
+	ASSERT(info != NULL);
+	ASSERT(event != NULL);
+	ASSERT(h != NULL);
+
+	if (info->netd_hooks == NULL)
+		return (ENXIO);
+
+	return (hook_unregister(info->netd_hooks, event, h));
+}
--- a/usr/src/uts/common/io/stream.c	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/io/stream.c	Fri Oct 20 16:37:58 2006 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -24,7 +23,7 @@
 
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1378,6 +1377,7 @@
 	mblk_t *bp, *b_cont;
 	dblk_t *dbp;
 	ssize_t n;
+	uint32_t start, stuff, end, value, flags;
 
 	ASSERT(mp->b_datap->db_ref > 0);
 	ASSERT(mp->b_next == NULL && mp->b_prev == NULL);
@@ -1421,6 +1421,13 @@
 	bp->b_datap->db_mblk = bp;
 	mp->b_rptr = mp->b_wptr = dbp->db_base;
 
+	/*
+	 * Need to preserve checksum information by copying them
+	 * to mp which heads the pulluped message.
+	 */
+	hcksum_retrieve(bp, NULL, NULL, &start, &stuff, &end, &value, &flags);
+	(void) hcksum_assoc(mp, NULL, NULL, start, stuff, end, value, flags, 0);
+
 	do {
 		ASSERT(bp->b_datap->db_ref > 0);
 		ASSERT(bp->b_wptr >= bp->b_rptr);
@@ -1453,6 +1460,7 @@
 	mblk_t	*newmp;
 	ssize_t	totlen;
 	ssize_t	n;
+	uint32_t start, stuff, end, value, flags;
 
 	/*
 	 * We won't handle Multidata message, since it contains
@@ -1481,6 +1489,14 @@
 	newmp->b_flag = mp->b_flag;
 	newmp->b_band = mp->b_band;
 
+	/*
+	 * Need to preserve checksum information by copying them
+	 * to newmp which heads the pulluped message.
+	 */
+	hcksum_retrieve(mp, NULL, NULL, &start, &stuff, &end, &value, &flags);
+	(void) hcksum_assoc(newmp, NULL, NULL, start, stuff, end,
+	    value, flags, 0);
+
 	while (len > 0) {
 		n = mp->b_wptr - mp->b_rptr;
 		ASSERT(n >= 0);		/* allow zero-length mblk_t's */
--- a/usr/src/uts/common/sys/Makefile	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/sys/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -246,6 +246,9 @@
 	gld.h			\
 	gldpriv.h		\
 	hdio.h			\
+	hook.h			\
+	hook_event.h		\
+	hook_impl.h		\
 	hwconf.h		\
 	ia.h			\
 	iapriocntl.h		\
@@ -339,6 +342,7 @@
 	ndifm.h		\
 	ndi_impldefs.h		\
 	netconfig.h		\
+	neti.h			\
 	nexusdefs.h		\
 	note.h			\
 	nvpair.h                \
@@ -353,6 +357,7 @@
 	pathconf.h		\
 	pathname.h		\
 	pattr.h			\
+	queue.h			\
 	serializer.h		\
 	pbio.h			\
 	pccard.h		\
--- a/usr/src/uts/common/sys/condvar_impl.h	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/sys/condvar_impl.h	Fri Oct 20 16:37:58 2006 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -19,9 +18,10 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright (c) 1991-1997 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
  */
 
 #ifndef _SYS_CONDVAR_IMPL_H
@@ -56,6 +56,52 @@
 
 #endif	/* _ASM */
 
+
+typedef	struct	cvwaitlock_s	{
+	kmutex_t	cvw_lock;
+	kcondvar_t	cvw_waiter;
+	int		cvw_refcnt;
+} cvwaitlock_t;
+
+
+#define	CVW_INIT(_c)		{				\
+	mutex_init(&(_c)->cvw_lock, NULL, MUTEX_DRIVER, NULL);	\
+	cv_init(&(_c)->cvw_waiter, NULL, CV_DRIVER, NULL);	\
+	(_c)->cvw_refcnt = 0;					\
+}
+
+#define	CVW_ENTER_READ(_c)	{				\
+	mutex_enter(&(_c)->cvw_lock);				\
+	while ((_c)->cvw_refcnt < 0)				\
+		cv_wait(&((_c)->cvw_waiter), &(_c)->cvw_lock);	\
+	(_c)->cvw_refcnt++;					\
+	mutex_exit(&(_c)->cvw_lock);				\
+}
+
+#define	CVW_ENTER_WRITE(_c)	{				\
+	mutex_enter(&(_c)->cvw_lock);				\
+	while ((_c)->cvw_refcnt != 0)				\
+		cv_wait(&((_c)->cvw_waiter), &(_c)->cvw_lock);	\
+	(_c)->cvw_refcnt = -1;					\
+	mutex_exit(&(_c)->cvw_lock);				\
+}
+
+#define	CVW_EXIT_READ(_c)	{			\
+	mutex_enter(&(_c)->cvw_lock);			\
+	ASSERT((_c)->cvw_refcnt > 0);			\
+	if ((--((_c)->cvw_refcnt)) == 0)		\
+		cv_broadcast(&(_c)->cvw_waiter);	\
+	mutex_exit(&(_c)->cvw_lock);			\
+}
+
+#define	CVW_EXIT_WRITE(_c)	{			\
+	mutex_enter(&(_c)->cvw_lock);			\
+	ASSERT((_c)->cvw_refcnt == -1);			\
+	(_c)->cvw_refcnt = 0;				\
+	cv_broadcast(&(_c)->cvw_waiter);		\
+	mutex_exit(&(_c)->cvw_lock);			\
+}
+
 #ifdef	__cplusplus
 }
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/hook.h	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,115 @@
+/*
+ * 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 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * This file includes definitions of kernel hook framework components
+ */
+
+#ifndef _SYS_HOOK_H
+#define	_SYS_HOOK_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/queue.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * Definition exposed to hook provider and consumer
+ */
+
+#define	HOOK_VERSION	1
+
+typedef uintptr_t hook_data_t;
+
+struct hook_event_int;
+typedef struct hook_event_int *hook_event_token_t;
+
+typedef int (* hook_func_t)(hook_event_token_t, hook_data_t);
+
+/*
+ * Hook
+ */
+typedef struct hook {
+	int32_t		h_version;	/* version number */
+	hook_func_t	h_func;		/* callback func */
+	char		*h_name;	/* name of this hook */
+	int		h_flags;	/* extra hook properties */
+} hook_t;
+
+#define	HOOK_INIT(x, fn, r)			\
+	do {					\
+		(x)->h_version = HOOK_VERSION;	\
+		(x)->h_func = (fn);		\
+		(x)->h_name = (r);		\
+		(x)->h_flags = 0;		\
+		_NOTE(CONSTCOND)		\
+	} while (0)
+
+/*
+ * Family
+ */
+typedef struct hook_family {
+	int32_t		hf_version;	/* version number */
+	char		*hf_name;	/* family name */
+} hook_family_t;
+
+#define	HOOK_FAMILY_INIT(x, y)			\
+	do {					\
+		(x)->hf_version = HOOK_VERSION;	\
+		(x)->hf_name = (y);		\
+		_NOTE(CONSTCOND)		\
+	} while (0)
+
+/*
+ * Event
+ */
+typedef struct hook_event {
+	int32_t		he_version;	/* version number */
+	char		*he_name;	/* name of this hook list */
+	int		he_flags;	/* 1 = multiple entries allowed */
+	boolean_t	he_interested;	/* true if callback exist */
+} hook_event_t;
+
+#define	HOOK_RDONLY	0x1		/* Callbacks must not change data */
+					/* Multiple callbacks are allowed */
+
+#define	HOOK_EVENT_INIT(x, y)			\
+	do {					\
+		(x)->he_version = HOOK_VERSION;	\
+		(x)->he_name = (y);		\
+		(x)->he_flags = 0;		\
+		(x)->he_interested = B_FALSE;	\
+		_NOTE(CONSTCOND)		\
+	} while (0)
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _SYS_HOOK_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/hook_event.h	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,100 @@
+/*
+ * 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 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * This file include definition of message passed from hook provider
+ * to hook consumer.  If necessary, each hook provider can add its
+ * own message definition here.
+ */
+
+#ifndef _SYS_HOOK_EVENT_H
+#define	_SYS_HOOK_EVENT_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/neti.h>
+#include <sys/hook.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * The hook_pkt_event_t structure is supplied with packet events on
+ * associated network interfaces.
+ *
+ * The members of this structure are defined as follows:
+ * hpe_ifp - "in" interface for packets coming into the system or forwarded
+ * hpe_ofp - "out" interface for packets being transmitted or forwarded
+ * hpe_hdr - pointer to protocol header within the packet
+ * hpe_mp  - pointer to the mblk pointer starting the chain for this packet
+ * hpe_mb  - pointer to the mblk that contains hpe_hdr
+ */
+typedef struct hook_pkt_event {
+	phy_if_t		hpe_ifp;
+	phy_if_t		hpe_ofp;
+	void			*hpe_hdr;
+	mblk_t			**hpe_mp;
+	mblk_t			*hpe_mb;
+} hook_pkt_event_t;
+
+/*
+ * NIC events hook provider
+ */
+typedef enum nic_event {
+	NE_PLUMB = 1,
+	NE_UNPLUMB,
+	NE_UP,
+	NE_DOWN,
+	NE_ADDRESS_CHANGE
+} nic_event_t;
+
+typedef void *nic_event_data_t;
+
+/*
+ * The hook_nic_event data structure is provided with all network interface
+ * events.
+ *
+ * hne_family  - network family of events, returned from net_lookup
+ * hne_nic     - physical interface associated with event
+ * hne_lif     - logical interface (if any) associated with event
+ * hne_event   - type of event occuring
+ * hne_data    - pointer to extra data about event or NULL if none
+ * hne_datalen - size of data pointed to by hne_data (can be 0)
+ */
+typedef struct hook_nic_event {
+	net_data_t		hne_family;
+	phy_if_t		hne_nic;
+	lif_if_t		hne_lif;
+	nic_event_t		hne_event;
+	nic_event_data_t	hne_data;
+	size_t			hne_datalen;
+} hook_nic_event_t;
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _SYS_HOOK_EVENT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/hook_impl.h	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,136 @@
+/*
+ * 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 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * This file include internal used definition and data structure of hooks
+ */
+
+#ifndef _SYS_HOOK_IMPL_H
+#define	_SYS_HOOK_IMPL_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/hook.h>
+#include <sys/condvar_impl.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * The following diagram describes the linking together of data structures
+ * used in this implementation of callback hooks.  The start of it all is
+ * the "familylist" variable in hook.c.  The relationships between data
+ * structures is:
+ * - there is a list of hook families;
+ * - each hook family can have a list of hook events;
+ * - each hook_event_t must be uniquely associated with one family and event;
+ * - each hook event can have a list of registered hooks to call.
+ *
+ *   familylist                    +--------------+
+ *       |                         | hook_event_t |<--\
+ *       |                         +--------------+   |
+ *       V                                            |
+ * +-------------------+       ->+------------------+ |     ->+--------------+
+ * | hook_family_int_t |      /  | hook_event_int_t | |    /  | hook_int_t   |
+ * | +---------------+ |     /   |                  | /   /   | +----------+ |
+ * | | hook_family_t | |    /    | hei_event---------/   /    | | hook_t   | |
+ * | +---------------+ |   /     |                  |   /     | +----------+ |
+ * |                   |  /      |                  |  /      |              |
+ * | hfi_head------------/       | hei_head-----------/       | hi_entry--\  |
+ * | hfi_entry--\      |         | hei_entry--\     |         +-----------|--+
+ * +------------|------+         +------------|-----+                     |
+ *              |                             |                           |
+ *              V                             V                           V
+ * +-------------------+         +------------------+         +--------------+
+ * | hook_family_int_t |         | hook_event_int_t |         | hook_int_t   |
+ * ...
+ */
+
+/*
+ * hook_int: internal storage of hook
+ */
+typedef struct hook_int {
+	TAILQ_ENTRY(hook_int)	hi_entry;
+	hook_t			hi_hook;
+} hook_int_t;
+
+/*
+ * Hook_int_head: tail queue of hook_int
+ */
+TAILQ_HEAD(hook_int_head, hook_int);
+typedef struct hook_int_head hook_int_head_t;
+
+/*
+ * hook_event_int: internal storage of hook_event
+ */
+typedef struct hook_event_int {
+	cvwaitlock_t			hei_lock;
+	SLIST_ENTRY(hook_event_int)	hei_entry;
+	hook_event_t			*hei_event;
+	hook_int_head_t			hei_head;
+} hook_event_int_t;
+
+/*
+ * hook_event_int_head: singly-linked list of hook_event_int
+ */
+SLIST_HEAD(hook_event_int_head, hook_event_int);
+typedef struct hook_event_int_head hook_event_int_head_t;
+
+/*
+ * hook_family_int: internal storage of hook_family
+ */
+typedef struct hook_family_int {
+	SLIST_ENTRY(hook_family_int)	hfi_entry;
+	hook_event_int_head_t		hfi_head;
+	hook_family_t 			hfi_family;
+} hook_family_int_t;
+
+/*
+ * hook_family_int_head: singly-linked list of hook_family
+ */
+SLIST_HEAD(hook_family_int_head, hook_family_int);
+typedef struct hook_family_int_head hook_family_int_head_t;
+
+/*
+ * Names of hooks families currently defined by Solaris
+ */
+#define	Hn_ARP	"arp"
+#define	Hn_IPV4	"inet"
+#define	Hn_IPV6	"inet6"
+
+extern hook_family_int_t *hook_family_add(hook_family_t *);
+extern int hook_family_remove(hook_family_int_t *);
+extern hook_event_int_t *hook_event_add(hook_family_int_t *, hook_event_t *);
+extern int hook_event_remove(hook_family_int_t *, hook_event_t *);
+extern int hook_register(hook_family_int_t *, char *, hook_t *);
+extern int hook_unregister(hook_family_int_t *, char *, hook_t *);
+extern int hook_run(hook_event_token_t, hook_data_t);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _SYS_HOOK_IMPL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/neti.h	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,197 @@
+/*
+ * 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 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NETI_H
+#define	_SYS_NETI_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <netinet/in.h>
+#include <sys/int_types.h>
+#include <sys/queue.h>
+#include <sys/hook_impl.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#define	NETINFO_VERSION 1
+
+/*
+ * Network hooks framework stack protocol name
+ */
+#define	NHF_INET	"NHF_INET"
+#define	NHF_INET6	"NHF_INET6"
+#define	NHF_ARP		"NHF_ARP"
+
+/*
+ * Event identification
+ */
+#define	NH_PHYSICAL_IN	"PHYSICAL_IN"
+#define	NH_PHYSICAL_OUT	"PHYSICAL_OUT"
+#define	NH_FORWARDING	"FORWARDING"
+#define	NH_LOOPBACK_IN	"LOOPBACK_IN"
+#define	NH_LOOPBACK_OUT	"LOOPBACK_OUT"
+#define	NH_NIC_EVENTS	"NIC_EVENTS"
+
+/*
+ * Network NIC hardware checksum capability
+ */
+#define	NET_HCK_NONE   	0x00
+#define	NET_HCK_L3_FULL	0x01
+#define	NET_HCK_L3_PART	0x02
+#define	NET_HCK_L4_FULL	0x10
+#define	NET_HCK_L4_PART	0x20
+
+#define	NET_IS_HCK_L3_FULL(n, x)                                             \
+	((net_ispartialchecksum(n, x) & NET_HCK_L3_FULL) == NET_HCK_L3_FULL)
+#define	NET_IS_HCK_L3_PART(n, x)                                             \
+	((net_ispartialchecksum(n, x) & NET_HCK_L3_PART) == NET_HCK_L3_PART)
+#define	NET_IS_HCK_L4_FULL(n, x)                                             \
+	((net_ispartialchecksum(n, x) & NET_HCK_L4_FULL) == NET_HCK_L4_FULL)
+#define	NET_IS_HCK_L4_PART(n, x)                                             \
+	((net_ispartialchecksum(n, x) & NET_HCK_L4_PART) == NET_HCK_L4_PART)
+#define	NET_IS_HCK_L34_FULL(n, x)                                            \
+	((net_ispartialchecksum(n, x) & (NET_HCK_L3_FULL|NET_HCK_L4_FULL))   \
+	    == (NET_HCK_L3_FULL | NET_HCK_L4_FULL))
+
+typedef uintptr_t	phy_if_t;
+typedef intptr_t	lif_if_t;
+typedef uintptr_t	net_ifdata_t;
+
+struct net_data;
+typedef struct net_data *net_data_t;
+
+/*
+ * Netinfo interface specification
+ *
+ * Netinfo provides an extensible and easy to use interface for
+ * accessing data and functionality already embedded within network
+ * code that exists within the kernel.
+ */
+typedef enum net_ifaddr {
+	NA_ADDRESS = 1,
+	NA_PEER,
+	NA_BROADCAST,
+	NA_NETMASK
+} net_ifaddr_t;
+
+
+typedef enum inject {
+	NI_QUEUE_IN = 1,
+	NI_QUEUE_OUT,
+	NI_DIRECT_OUT
+} inject_t;
+
+typedef struct net_inject {
+	mblk_t			*ni_packet;
+	struct sockaddr_storage	ni_addr;
+	phy_if_t		ni_physical;
+} net_inject_t;
+
+
+/*
+ * net_info_t public interface
+ */
+typedef struct net_info {
+	int		neti_version;
+	char		*neti_protocol;
+	int		(*neti_getifname)(phy_if_t, char *, const size_t);
+	int		(*neti_getmtu)(phy_if_t, lif_if_t);
+	int		(*neti_getpmtuenabled)(void);
+	int		(*neti_getlifaddr)(phy_if_t, lif_if_t, size_t,
+			    net_ifaddr_t [], void *);
+	phy_if_t	(*neti_phygetnext)(phy_if_t);
+	phy_if_t	(*neti_phylookup)(const char *);
+	lif_if_t	(*neti_lifgetnext)(phy_if_t, lif_if_t);
+	int		(*neti_inject)(inject_t, net_inject_t *);
+	phy_if_t	(*neti_routeto)(struct sockaddr *);
+	int		(*neti_ispartialchecksum)(mblk_t *);
+	int		(*neti_isvalidchecksum)(mblk_t *);
+} net_info_t;
+
+
+/*
+ * Private data structures
+ */
+struct net_data {
+	LIST_ENTRY(net_data)		netd_list;
+	net_info_t			netd_info;
+	int				netd_refcnt;
+	hook_family_int_t		*netd_hooks;
+};
+
+
+typedef struct injection_s {
+	net_inject_t	inj_data;
+	boolean_t	inj_isv6;
+} injection_t;
+
+/*
+ * The ipif_id space is [0,MAX) but this interface wants to return [1,MAX] as
+ * a valid range of logical interface numbers so that it can return 0 to mean
+ * "end of list" with net_lifgetnext.  Changing ipif_id's to use the [1,MAX]
+ * space is something to be considered for the future, if it is worthwhile.
+ */
+#define	MAP_IPIF_ID(x)		((x) + 1)
+#define	UNMAP_IPIF_ID(x)	(((x) > 0) ? (x) - 1 : (x))
+
+
+/*
+ * Data management functions
+ */
+extern net_data_t net_register(const net_info_t *);
+extern int net_unregister(net_data_t);
+extern net_data_t net_lookup(const char *);
+extern int net_release(net_data_t);
+extern net_data_t net_walk(net_data_t);
+
+/*
+ * Accessor functions
+ */
+extern int net_register_family(net_data_t, hook_family_t *);
+extern int net_unregister_family(net_data_t, hook_family_t *);
+extern hook_event_token_t net_register_event(net_data_t, hook_event_t *);
+extern int net_unregister_event(net_data_t, hook_event_t *);
+extern int net_register_hook(net_data_t, char *, hook_t *);
+extern int net_unregister_hook(net_data_t, char *, hook_t *);
+extern int net_getifname(net_data_t, phy_if_t, char *, const size_t);
+extern int net_getmtu(net_data_t, phy_if_t, lif_if_t);
+extern int net_getpmtuenabled(net_data_t);
+extern int net_getlifaddr(net_data_t, phy_if_t, lif_if_t,
+    int, net_ifaddr_t [], void *);
+extern phy_if_t net_phygetnext(net_data_t, phy_if_t);
+extern phy_if_t net_phylookup(net_data_t, const char *);
+extern lif_if_t net_lifgetnext(net_data_t, phy_if_t, lif_if_t);
+extern int net_inject(net_data_t, inject_t, net_inject_t *);
+extern phy_if_t net_routeto(net_data_t, struct sockaddr *);
+extern int net_ispartialchecksum(net_data_t, mblk_t *);
+extern int net_isvalidchecksum(net_data_t, mblk_t *);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _SYS_NETI_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/queue.h	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,667 @@
+/*	$NetBSD: queue.h,v 1.42 2005/07/13 15:08:24 wiz Exp $	*/
+
+/*
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)queue.h	8.5 (Berkeley) 8/20/94
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_SYS_QUEUE_H
+#define	_SYS_QUEUE_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/note.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * This file defines five types of data structures: singly-linked lists,
+ * lists, simple queues, tail queues, and circular queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The
+ * elements are singly linked for minimum space and pointer manipulation
+ * overhead at the expense of O(n) removal for arbitrary elements. New
+ * elements can be added to the list after an existing element or at the
+ * head of the list.  Elements being removed from the head of the list
+ * should use the explicit macro for this purpose for optimum
+ * efficiency. A singly-linked list may only be traversed in the forward
+ * direction.  Singly-linked lists are ideal for applications with large
+ * datasets and few or no removals or for implementing a LIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so elements can only be removed from the
+ * head of the list. New elements can be added to the list after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * List definitions.
+ */
+#define	LIST_HEAD(name, type)						\
+struct name {								\
+	struct type *lh_first;	/* first element */			\
+}
+
+#define	LIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define	LIST_ENTRY(type)						\
+struct {								\
+	struct type *le_next;	/* next element */			\
+	struct type **le_prev;	/* address of previous next element */	\
+}
+
+/*
+ * List functions.
+ */
+#if defined(_KERNEL) && defined(QUEUEDEBUG)
+#define	QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field)			\
+	if ((head)->lh_first &&						\
+	    (head)->lh_first->field.le_prev != &(head)->lh_first)	\
+		panic("LIST_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__);
+#define	QUEUEDEBUG_LIST_OP(elm, field)					\
+	if ((elm)->field.le_next &&					\
+	    (elm)->field.le_next->field.le_prev !=			\
+	    &(elm)->field.le_next)					\
+		panic("LIST_* forw %p %s:%d", (elm), __FILE__, __LINE__);\
+	if (*(elm)->field.le_prev != (elm))				\
+		panic("LIST_* back %p %s:%d", (elm), __FILE__, __LINE__);
+#define	QUEUEDEBUG_LIST_POSTREMOVE(elm, field)				\
+	(elm)->field.le_next = (void *)1L;				\
+	(elm)->field.le_prev = (void *)1L;
+#else
+#define	QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field)
+#define	QUEUEDEBUG_LIST_OP(elm, field)
+#define	QUEUEDEBUG_LIST_POSTREMOVE(elm, field)
+#endif
+
+#define	LIST_INIT(head) do {						\
+	(head)->lh_first = NULL;					\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	LIST_INSERT_AFTER(listelm, elm, field) do {			\
+	QUEUEDEBUG_LIST_OP((listelm), field)				\
+	if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)	\
+		(listelm)->field.le_next->field.le_prev =		\
+		    &(elm)->field.le_next;				\
+	(listelm)->field.le_next = (elm);				\
+	(elm)->field.le_prev = &(listelm)->field.le_next;		\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
+	QUEUEDEBUG_LIST_OP((listelm), field)				\
+	(elm)->field.le_prev = (listelm)->field.le_prev;		\
+	(elm)->field.le_next = (listelm);				\
+	*(listelm)->field.le_prev = (elm);				\
+	(listelm)->field.le_prev = &(elm)->field.le_next;		\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	LIST_INSERT_HEAD(head, elm, field) do {				\
+	QUEUEDEBUG_LIST_INSERT_HEAD((head), (elm), field)		\
+	if (((elm)->field.le_next = (head)->lh_first) != NULL)		\
+		(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+	(head)->lh_first = (elm);					\
+	(elm)->field.le_prev = &(head)->lh_first;			\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	LIST_REMOVE(elm, field) do {					\
+	QUEUEDEBUG_LIST_OP((elm), field)				\
+	if ((elm)->field.le_next != NULL)				\
+		(elm)->field.le_next->field.le_prev = 			\
+		    (elm)->field.le_prev;				\
+	*(elm)->field.le_prev = (elm)->field.le_next;			\
+	QUEUEDEBUG_LIST_POSTREMOVE((elm), field)			\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	LIST_FOREACH(var, head, field)					\
+	for ((var) = ((head)->lh_first);				\
+		(var);							\
+		(var) = ((var)->field.le_next))
+
+/*
+ * List access methods.
+ */
+#define	LIST_EMPTY(head)		((head)->lh_first == NULL)
+#define	LIST_FIRST(head)		((head)->lh_first)
+#define	LIST_NEXT(elm, field)		((elm)->field.le_next)
+
+
+/*
+ * Singly-linked List definitions.
+ */
+#define	SLIST_HEAD(name, type)						\
+struct name {								\
+	struct type *slh_first;	/* first element */			\
+}
+
+#define	SLIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define	SLIST_ENTRY(type)						\
+struct {								\
+	struct type *sle_next;	/* next element */			\
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define	SLIST_INIT(head) do {						\
+	(head)->slh_first = NULL;					\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
+	(elm)->field.sle_next = (slistelm)->field.sle_next;		\
+	(slistelm)->field.sle_next = (elm);				\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	SLIST_INSERT_HEAD(head, elm, field) do {			\
+	(elm)->field.sle_next = (head)->slh_first;			\
+	(head)->slh_first = (elm);					\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	SLIST_REMOVE_HEAD(head, field) do {				\
+	(head)->slh_first = (head)->slh_first->field.sle_next;		\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	SLIST_REMOVE(head, elm, type, field) do {			\
+	if ((head)->slh_first == (elm)) {				\
+		SLIST_REMOVE_HEAD((head), field);			\
+	}								\
+	else {								\
+		struct type *curelm = (head)->slh_first;		\
+		while (curelm->field.sle_next != (elm))			\
+			curelm = curelm->field.sle_next;		\
+		curelm->field.sle_next =				\
+		    curelm->field.sle_next->field.sle_next;		\
+	}								\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	SLIST_FOREACH(var, head, field)					\
+	for ((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
+
+/*
+ * Singly-linked List access methods.
+ */
+#define	SLIST_EMPTY(head)	((head)->slh_first == NULL)
+#define	SLIST_FIRST(head)	((head)->slh_first)
+#define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
+
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define	STAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *stqh_first;	/* first element */		\
+	struct type **stqh_last;	/* addr of last next element */	\
+}
+
+#define	STAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).stqh_first }
+
+#define	STAILQ_ENTRY(type)						\
+struct {								\
+	struct type *stqe_next;	/* next element */		\
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define	STAILQ_INIT(head) do {						\
+	(head)->stqh_first = NULL;					\
+	(head)->stqh_last = &(head)->stqh_first;			\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if (((elm)->field.stqe_next = (head)->stqh_first) == NULL)	\
+		(head)->stqh_last = &(elm)->field.stqe_next;		\
+	(head)->stqh_first = (elm);					\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.stqe_next = NULL;					\
+	*(head)->stqh_last = (elm);					\
+	(head)->stqh_last = &(elm)->field.stqe_next;			\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	STAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if (((elm)->field.stqe_next = (listelm)->field.stqe_next)	\
+	    == NULL)							\
+		(head)->stqh_last = &(elm)->field.stqe_next;		\
+	(listelm)->field.stqe_next = (elm);				\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	STAILQ_REMOVE_HEAD(head, field) do {				\
+	if (((head)->stqh_first = (head)->stqh_first->field.stqe_next)	\
+	    == NULL) 							\
+		(head)->stqh_last = &(head)->stqh_first;		\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	STAILQ_REMOVE(head, elm, type, field) do {			\
+	if ((head)->stqh_first == (elm)) {				\
+		STAILQ_REMOVE_HEAD((head), field);			\
+	} else {							\
+		struct type *curelm = (head)->stqh_first;		\
+		while (curelm->field.stqe_next != (elm))		\
+			curelm = curelm->field.stqe_next;		\
+		if ((curelm->field.stqe_next =				\
+			curelm->field.stqe_next->field.stqe_next) == NULL) \
+			    (head)->stqh_last = &(curelm)->field.stqe_next; \
+	}								\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	STAILQ_FOREACH(var, head, field)				\
+	for ((var) = ((head)->stqh_first);				\
+		(var);							\
+		(var) = ((var)->field.stqe_next))
+
+/*
+ * Singly-linked Tail queue access methods.
+ */
+#define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL)
+#define	STAILQ_FIRST(head)	((head)->stqh_first)
+#define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
+
+
+/*
+ * Simple queue definitions.
+ */
+#define	SIMPLEQ_HEAD(name, type)					\
+struct name {								\
+	struct type *sqh_first;	/* first element */		\
+	struct type **sqh_last;	/* addr of last next element */	\
+}
+
+#define	SIMPLEQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).sqh_first }
+
+#define	SIMPLEQ_ENTRY(type)						\
+struct {								\
+	struct type *sqe_next;	/* next element */			\
+}
+
+/*
+ * Simple queue functions.
+ */
+#define	SIMPLEQ_INIT(head) do {						\
+	(head)->sqh_first = NULL;					\
+	(head)->sqh_last = &(head)->sqh_first;				\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	SIMPLEQ_INSERT_HEAD(head, elm, field) do {			\
+	if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)	\
+		(head)->sqh_last = &(elm)->field.sqe_next;		\
+	(head)->sqh_first = (elm);					\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	SIMPLEQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.sqe_next = NULL;					\
+	*(head)->sqh_last = (elm);					\
+	(head)->sqh_last = &(elm)->field.sqe_next;			\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+		(head)->sqh_last = &(elm)->field.sqe_next;		\
+	(listelm)->field.sqe_next = (elm);				\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	SIMPLEQ_REMOVE_HEAD(head, field) do {				\
+	if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
+		(head)->sqh_last = &(head)->sqh_first;			\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	SIMPLEQ_REMOVE(head, elm, type, field) do {			\
+	if ((head)->sqh_first == (elm)) {				\
+		SIMPLEQ_REMOVE_HEAD((head), field);			\
+	} else {							\
+		struct type *curelm = (head)->sqh_first;		\
+		while (curelm->field.sqe_next != (elm))			\
+			curelm = curelm->field.sqe_next;		\
+		if ((curelm->field.sqe_next =				\
+			curelm->field.sqe_next->field.sqe_next) == NULL) \
+			    (head)->sqh_last = &(curelm)->field.sqe_next; \
+	}								\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	SIMPLEQ_FOREACH(var, head, field)				\
+	for ((var) = ((head)->sqh_first);				\
+		(var);							\
+		(var) = ((var)->field.sqe_next))
+
+/*
+ * Simple queue access methods.
+ */
+#define	SIMPLEQ_EMPTY(head)		((head)->sqh_first == NULL)
+#define	SIMPLEQ_FIRST(head)		((head)->sqh_first)
+#define	SIMPLEQ_NEXT(elm, field)	((elm)->field.sqe_next)
+
+
+/*
+ * Tail queue definitions.
+ */
+#define	_TAILQ_HEAD(name, type)						\
+struct name {								\
+	type *tqh_first;		/* first element */		\
+	type **tqh_last;	/* addr of last next element */		\
+}
+#define	TAILQ_HEAD(name, type)	_TAILQ_HEAD(name, struct type)
+
+#define	TAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).tqh_first }
+
+#define	_TAILQ_ENTRY(type)						\
+struct {								\
+	type *tqe_next;		/* next element */			\
+	type **tqe_prev;	/* address of previous next element */\
+}
+#define	TAILQ_ENTRY(type)	_TAILQ_ENTRY(struct type)
+
+/*
+ * Tail queue functions.
+ */
+#if defined(_KERNEL) && defined(QUEUEDEBUG)
+#define	QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field)			\
+	if ((head)->tqh_first &&					\
+	    (head)->tqh_first->field.tqe_prev != &(head)->tqh_first)	\
+		panic("TAILQ_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__);
+#define	QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field)			\
+	if (*(head)->tqh_last != NULL)					\
+		panic("TAILQ_INSERT_TAIL %p %s:%d", (head), __FILE__, __LINE__);
+#define	QUEUEDEBUG_TAILQ_OP(elm, field)					\
+	if ((elm)->field.tqe_next &&					\
+	    (elm)->field.tqe_next->field.tqe_prev !=			\
+	    &(elm)->field.tqe_next)					\
+		panic("TAILQ_* forw %p %s:%d", (elm), __FILE__, __LINE__);\
+	if (*(elm)->field.tqe_prev != (elm))				\
+		panic("TAILQ_* back %p %s:%d", (elm), __FILE__, __LINE__);
+#define	QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field)			\
+	if ((elm)->field.tqe_next == NULL &&				\
+	    (head)->tqh_last != &(elm)->field.tqe_next)			\
+		panic("TAILQ_PREREMOVE head %p elm %p %s:%d",		\
+		(head), (elm), __FILE__, __LINE__);
+#define	QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field)				\
+	(elm)->field.tqe_next = (void *)1L;				\
+	(elm)->field.tqe_prev = (void *)1L;
+#else
+#define	QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field)
+#define	QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field)
+#define	QUEUEDEBUG_TAILQ_OP(elm, field)
+#define	QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field)
+#define	QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field)
+#endif
+
+#define	TAILQ_INIT(head) do {						\
+	(head)->tqh_first = NULL;					\
+	(head)->tqh_last = &(head)->tqh_first;				\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
+	QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field)		\
+	if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)	\
+		(head)->tqh_first->field.tqe_prev =			\
+		    &(elm)->field.tqe_next;				\
+	else								\
+		(head)->tqh_last = &(elm)->field.tqe_next;		\
+	(head)->tqh_first = (elm);					\
+	(elm)->field.tqe_prev = &(head)->tqh_first;			\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
+	QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field)		\
+	(elm)->field.tqe_next = NULL;					\
+	(elm)->field.tqe_prev = (head)->tqh_last;			\
+	*(head)->tqh_last = (elm);					\
+	(head)->tqh_last = &(elm)->field.tqe_next;			\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	QUEUEDEBUG_TAILQ_OP((listelm), field)				\
+	if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+		(elm)->field.tqe_next->field.tqe_prev = 		\
+		    &(elm)->field.tqe_next;				\
+	else								\
+		(head)->tqh_last = &(elm)->field.tqe_next;		\
+	(listelm)->field.tqe_next = (elm);				\
+	(elm)->field.tqe_prev = &(listelm)->field.tqe_next;		\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
+	QUEUEDEBUG_TAILQ_OP((listelm), field)				\
+	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
+	(elm)->field.tqe_next = (listelm);				\
+	*(listelm)->field.tqe_prev = (elm);				\
+	(listelm)->field.tqe_prev = &(elm)->field.tqe_next;		\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	TAILQ_REMOVE(head, elm, field) do {				\
+	QUEUEDEBUG_TAILQ_PREREMOVE((head), (elm), field)		\
+	QUEUEDEBUG_TAILQ_OP((elm), field)				\
+	if (((elm)->field.tqe_next) != NULL)				\
+		(elm)->field.tqe_next->field.tqe_prev = 		\
+		    (elm)->field.tqe_prev;				\
+	else								\
+		(head)->tqh_last = (elm)->field.tqe_prev;		\
+	*(elm)->field.tqe_prev = (elm)->field.tqe_next;			\
+	QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field);			\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	TAILQ_FOREACH(var, head, field)					\
+	for ((var) = ((head)->tqh_first);				\
+		(var);							\
+		(var) = ((var)->field.tqe_next))
+
+#define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
+	for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last));\
+		(var);							\
+		(var) = 						\
+		    (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
+
+/*
+ * Tail queue access methods.
+ */
+#define	TAILQ_EMPTY(head)		((head)->tqh_first == NULL)
+#define	TAILQ_FIRST(head)		((head)->tqh_first)
+#define	TAILQ_NEXT(elm, field)		((elm)->field.tqe_next)
+
+#define	TAILQ_LAST(head, headname) \
+	(*(((struct headname *)((head)->tqh_last))->tqh_last))
+#define	TAILQ_PREV(elm, headname, field) \
+	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+
+/*
+ * Circular queue definitions.
+ */
+#define	CIRCLEQ_HEAD(name, type)					\
+struct name {								\
+	struct type *cqh_first;		/* first element */	\
+	struct type *cqh_last;		/* last element */		\
+}
+
+#define	CIRCLEQ_HEAD_INITIALIZER(head)					\
+	{ (void *)&head, (void *)&head }
+
+#define	CIRCLEQ_ENTRY(type)						\
+struct {								\
+	struct type *cqe_next;		/* next element */		\
+	struct type *cqe_prev;		/* previous element */		\
+}
+
+/*
+ * Circular queue functions.
+ */
+#define	CIRCLEQ_INIT(head) do {						\
+	(head)->cqh_first = (void *)(head);				\
+	(head)->cqh_last = (void *)(head);				\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	(elm)->field.cqe_next = (listelm)->field.cqe_next;		\
+	(elm)->field.cqe_prev = (listelm);				\
+	if ((listelm)->field.cqe_next == (void *)(head))		\
+		(head)->cqh_last = (elm);				\
+	else								\
+		(listelm)->field.cqe_next->field.cqe_prev = (elm);	\
+	(listelm)->field.cqe_next = (elm);				\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {		\
+	(elm)->field.cqe_next = (listelm);				\
+	(elm)->field.cqe_prev = (listelm)->field.cqe_prev;		\
+	if ((listelm)->field.cqe_prev == (void *)(head))		\
+		(head)->cqh_first = (elm);				\
+	else								\
+		(listelm)->field.cqe_prev->field.cqe_next = (elm);	\
+	(listelm)->field.cqe_prev = (elm);				\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	CIRCLEQ_INSERT_HEAD(head, elm, field) do {			\
+	(elm)->field.cqe_next = (head)->cqh_first;			\
+	(elm)->field.cqe_prev = (void *)(head);				\
+	if ((head)->cqh_last == (void *)(head))			\
+		(head)->cqh_last = (elm);				\
+	else								\
+		(head)->cqh_first->field.cqe_prev = (elm);		\
+	(head)->cqh_first = (elm);					\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	CIRCLEQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.cqe_next = (void *)(head);				\
+	(elm)->field.cqe_prev = (head)->cqh_last;			\
+	if ((head)->cqh_first == (void *)(head))			\
+		(head)->cqh_first = (elm);				\
+	else								\
+		(head)->cqh_last->field.cqe_next = (elm);		\
+	(head)->cqh_last = (elm);					\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	CIRCLEQ_REMOVE(head, elm, field) do {				\
+	if ((elm)->field.cqe_next == (void *)(head))			\
+		(head)->cqh_last = (elm)->field.cqe_prev;		\
+	else								\
+		(elm)->field.cqe_next->field.cqe_prev =			\
+		    (elm)->field.cqe_prev;				\
+	if ((elm)->field.cqe_prev == (void *)(head))			\
+		(head)->cqh_first = (elm)->field.cqe_next;		\
+	else								\
+		(elm)->field.cqe_prev->field.cqe_next =			\
+		    (elm)->field.cqe_next;				\
+	_NOTE(CONSTCOND)						\
+} while (0)
+
+#define	CIRCLEQ_FOREACH(var, head, field)				\
+	for ((var) = ((head)->cqh_first);				\
+		(var) != (void *)(head);				\
+		(var) = ((var)->field.cqe_next))
+
+#define	CIRCLEQ_FOREACH_REVERSE(var, head, field)			\
+	for ((var) = ((head)->cqh_last);				\
+		(var) != (void *)(head);				\
+		(var) = ((var)->field.cqe_prev))
+
+/*
+ * Circular queue access methods.
+ */
+#define	CIRCLEQ_EMPTY(head)		((head)->cqh_first == (void *)(head))
+#define	CIRCLEQ_FIRST(head)		((head)->cqh_first)
+#define	CIRCLEQ_LAST(head)		((head)->cqh_last)
+#define	CIRCLEQ_NEXT(elm, field)	((elm)->field.cqe_next)
+#define	CIRCLEQ_PREV(elm, field)	((elm)->field.cqe_prev)
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* !_SYS_QUEUE_H */
--- a/usr/src/uts/common/sys/stream.h	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/common/sys/stream.h	Fri Oct 20 16:37:58 2006 -0700
@@ -393,8 +393,8 @@
 /*
  * db_flags values (all implementation private!)
  */
-#define	DBLK_REFMIN	0x01		/* min refcnt stored in low bit */
-#define	DBLK_COOKED	0x02		/* message has been processed once */
+#define	DBLK_REFMIN		0x01	/* min refcnt stored in low bit */
+#define	DBLK_COOKED		0x02	/* message has been processed once */
 
 /*
  * db_struioflag values:
--- a/usr/src/uts/intel/Makefile.intel.shared	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/intel/Makefile.intel.shared	Fri Oct 20 16:37:58 2006 -0700
@@ -258,7 +258,6 @@
 DRV_KMODS	+= mouse8042
 DRV_KMODS	+= nca
 DRV_KMODS	+= openeepr
-DRV_KMODS	+= pfil
 DRV_KMODS	+= pm
 DRV_KMODS	+= poll
 DRV_KMODS	+= pool
@@ -478,6 +477,7 @@
 MISC_KMODS	+= gda
 MISC_KMODS	+= gld
 MISC_KMODS	+= hidparser
+MISC_KMODS	+= hook
 MISC_KMODS	+= hpcsvc
 MISC_KMODS_32	+= i2o_msg
 MISC_KMODS	+= ibcm
@@ -495,6 +495,7 @@
 MISC_KMODS	+= mixer
 MISC_KMODS	+= nfs_dlboot
 MISC_KMODS	+= nfssrv
+MISC_KMODS	+= neti
 MISC_KMODS	+= pcicfg
 MISC_KMODS	+= pcihp
 MISC_KMODS	+= pcmcia
--- a/usr/src/uts/intel/arp/Makefile	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/intel/arp/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# 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.
@@ -22,7 +21,7 @@
 #
 # uts/intel/arp/Makefile
 #
-# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -69,7 +68,7 @@
 #
 #	depends on ip
 #
-LDFLAGS		+= -dy -Ndrv/ip
+LDFLAGS		+= -dy -Ndrv/ip -Ndrv/hook -Nmisc/neti
 
 #
 #	Default build targets.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/intel/hook/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,86 @@
+#
+# 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
+#
+#
+# uts/intel/hook/Makefile
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+#
+#	This makefile drives the production of the hook driver kernel module.
+#
+#	INTEL implementation architecture dependent
+#
+
+#
+#	Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE	= ../..
+
+#
+#	Define the module and object file sets.
+#
+MODULE		= hook
+OBJECTS		= $(HOOK_OBJS:%=$(OBJS_DIR)/%)
+LINTS		= $(HOOK_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE	= $(ROOT_MISC_DIR)/$(MODULE)
+
+
+#
+#	Include common rules.
+#
+include $(UTSBASE)/intel/Makefile.intel
+
+#
+#	Define targets
+#
+ALL_TARGET	= $(BINARY)
+LINT_TARGET	= $(MODULE).lint
+INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOTLINK)
+
+
+#
+#	Default build targets.
+#
+.KEEP_STATE:
+
+def:		$(DEF_DEPS)
+
+all:		$(ALL_DEPS)
+
+clean:		$(CLEAN_DEPS)
+
+clobber:	$(CLOBBER_DEPS)
+
+lint:		$(LINT_DEPS)
+
+modlintlib:	$(MODLINTLIB_DEPS)
+
+clean.lint:	$(CLEAN_LINT_DEPS)
+
+install:	$(INSTALL_DEPS)
+
+
+#
+#	Include common targets.
+#
+include $(UTSBASE)/intel/Makefile.targ
--- a/usr/src/uts/intel/ip/Makefile	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/intel/ip/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# 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.
@@ -20,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
@@ -67,7 +66,7 @@
 # swrand as it needs random numbers early on during boot before
 # kCF subsystem can load swrand.
 #
-LDFLAGS		+= -dy -Nmisc/md5 -Ncrypto/swrand
+LDFLAGS		+= -dy -Nmisc/md5 -Ncrypto/swrand -Nmisc/hook -Nmisc/neti 
 
 #
 #	Default build targets.
--- a/usr/src/uts/intel/ipf/Makefile	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/intel/ipf/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -1,3 +1,23 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
@@ -41,7 +61,7 @@
 MINOR=	    echo $(RELEASE) | cut -d. -f2
 CPPFLAGS += -DIPFILTER_LKM -DIPFILTER_LOG -DIPFILTER_LOOKUP -DUSE_INET6
 CPPFLAGS += -DSUNDDI -DSOLARIS2=$(MINOR:sh) -DIRE_ILL_CN
-LDFLAGS += -dy -Ndrv/ip -Ndrv/pfil -Nmisc/md5
+LDFLAGS += -dy -Ndrv/ip -Nmisc/md5 -Nmisc/neti
 
 INC_PATH += -I$(UTSBASE)/common/inet/ipf
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/intel/neti/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,86 @@
+#
+# 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
+#
+#
+#
+# uts/intel/neti/Makefile
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+#
+#	This makefile drives the production of the neti driver kernel module.
+#
+#	INTEL implementation architecture dependent
+#
+
+#
+#	Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE	= ../..
+
+#
+#	Define the module and object file sets.
+#
+MODULE		= neti
+OBJECTS		= $(NETI_OBJS:%=$(OBJS_DIR)/%)
+LINTS		= $(NETI_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE	= $(ROOT_MISC_DIR)/$(MODULE)
+
+#
+#	Include common rules.
+#
+include $(UTSBASE)/intel/Makefile.intel
+
+#
+#	Define targets
+#
+ALL_TARGET	= $(BINARY)
+LINT_TARGET	= $(MODULE).lint
+INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOTLINK)
+
+LDFLAGS		+= -dy -Nmisc/hook
+
+#
+#	Default build targets.
+#
+.KEEP_STATE:
+
+def:		$(DEF_DEPS)
+
+all:		$(ALL_DEPS)
+
+clean:		$(CLEAN_DEPS)
+
+clobber:	$(CLOBBER_DEPS)
+
+lint:		$(LINT_DEPS)
+
+modlintlib:	$(MODLINTLIB_DEPS)
+
+clean.lint:	$(CLEAN_LINT_DEPS)
+
+install:	$(INSTALL_DEPS)
+
+#
+#	Include common targets.
+#
+include $(UTSBASE)/intel/Makefile.targ
--- a/usr/src/uts/intel/os/device_policy	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/intel/os/device_policy	Fri Oct 20 16:37:58 2006 -0700
@@ -84,5 +84,4 @@
 # IP Filter
 #
 ipf             read_priv_set=sys_net_config    write_priv_set=sys_net_config
-pfil            read_priv_set=net_rawaccess     write_priv_set=net_rawaccess
 
--- a/usr/src/uts/intel/os/minor_perm	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/intel/os/minor_perm	Fri Oct 20 16:37:58 2006 -0700
@@ -107,7 +107,6 @@
 cryptoadm:cryptoadm 0644 root sys
 crypto:crypto 0666 root sys
 ipf:* 0666 root sys
-pfil:* 0666 root sys
 bl:* 0666 root sys
 sctp:* 0666 root sys
 sctp6:* 0666 root sys
--- a/usr/src/uts/intel/os/name_to_major	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/intel/os/name_to_major	Fri Oct 20 16:37:58 2006 -0700
@@ -98,7 +98,6 @@
 pool 163
 zcons 164
 ipf 165
-pfil 166
 fasttrap 167
 bl 168
 mpt 169
--- a/usr/src/uts/intel/pfil/Makefile	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-#
-# 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 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#ident	"%Z%%M%	%I%	%E% SMI"
-#
-# uts/intel/pfil/Makefile
-#
-#	This makefile drives the production of the pfil driver 
-#	kernel module.
-#
-#	intel architecture dependent
-#
-
-#
-#	Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE	= ../..
-
-#
-#	Define the module and object file sets.
-#
-MODULE		= pfil
-OBJECTS		= $(PFIL_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(PFIL_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_DRV_DIR)/$(MODULE)
-ROOTLINK	= $(ROOT_STRMOD_DIR)/$(MODULE)
-CONF_SRCDIR	= $(UTSBASE)/common/inet/pfil
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/intel/Makefile.intel
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(BINARY) $(SRC_CONFFILE)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOTLINK) $(ROOT_CONFFILE)
-
-MINOR=       echo $(RELEASE) | cut -d. -f2
-CPPFLAGS +=  -DSUNDDI -DSOLARIS2=$(MINOR:sh) -DIRE_ILL_CN -DSOLARIS -DUSE_INET6
-LDFLAGS += -dy -Ndrv/ip 
-
-#
-#	Default build targets.
-#
-.KEEP_STATE:
-
-def:		$(DEF_DEPS)
-
-all:		$(ALL_DEPS)
-
-clean:		$(CLEAN_DEPS)
-
-clobber:	$(CLOBBER_DEPS)
-
-lint:		$(LINT_DEPS)
-
-modlintlib:	$(MODLINTLIB_DEPS)
-
-clean.lint:	$(CLEAN_LINT_DEPS)
-
-install:	$(INSTALL_DEPS)
-
-$(ROOTLINK):	$(ROOT_STRMOD_DIR) $(ROOTMODULE)
-	-$(RM) $@; ln $(ROOTMODULE) $@
-
-#
-#	Include common targets.
-#
-include $(UTSBASE)/intel/Makefile.targ
--- a/usr/src/uts/sparc/Makefile.sparc.shared	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/sparc/Makefile.sparc.shared	Fri Oct 20 16:37:58 2006 -0700
@@ -234,7 +234,7 @@
 DRV_KMODS	+= tcp tcp6 tl tnf ttymux udp udp6 wc winlock zcons
 DRV_KMODS	+= ippctl sctp sctp6
 DRV_KMODS	+= dld
-DRV_KMODS	+= ipf pfil
+DRV_KMODS	+= ipf
 DRV_KMODS	+= rpcib
 DRV_KMODS	+= vni
 DRV_KMODS	+= xge
@@ -371,6 +371,8 @@
 MISC_KMODS	+= ibdm
 MISC_KMODS	+= ibmf
 MISC_KMODS	+= ibtl
+MISC_KMODS	+= hook
+MISC_KMODS	+= neti
 MISC_KMODS	+= ctf 
 MISC_KMODS	+= zmod
 MISC_KMODS	+= mac dls
--- a/usr/src/uts/sparc/arp/Makefile	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/sparc/arp/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# 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.
@@ -21,7 +20,7 @@
 #
 #
 # uts/sparc/arp/Makefile
-# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
@@ -73,7 +72,7 @@
 #
 #	depends on ip
 #
-LDFLAGS		+= -dy -Ndrv/ip
+LDFLAGS		+= -dy -Ndrv/ip -Ndrv/hook -Nmisc/neti
 
 #
 #	Default build targets.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/sparc/hook/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,88 @@
+#
+# 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
+#
+#
+# uts/sparc/hook/Makefile
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+#
+#	This makefile drives the production of the hook driver kernel module.
+#
+#	SPARC architecture dependent
+#
+
+#
+#	Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE	= ../..
+
+#
+#	Define the module and object file sets.
+#
+MODULE		= hook
+OBJECTS		= $(HOOK_OBJS:%=$(OBJS_DIR)/%)
+LINTS		= $(HOOK_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE	= $(ROOT_MISC_DIR)/$(MODULE)
+
+#
+#	Include common rules.
+#
+include $(UTSBASE)/sparc/Makefile.sparc
+
+#
+#	Define targets
+#
+ALL_TARGET	= $(BINARY)
+LINT_TARGET	= $(MODULE).lint
+INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOTLINK)
+
+#
+# lint pass one enforcement
+#
+CFLAGS		+= $(CCVERBOSE)
+
+#
+#	Default build targets.
+#
+.KEEP_STATE:
+
+def:		$(DEF_DEPS)
+
+all:		$(ALL_DEPS)
+
+clean:		$(CLEAN_DEPS)
+
+clobber:	$(CLOBBER_DEPS)
+
+lint:		$(LINT_DEPS)
+
+modlintlib:	$(MODLINTLIB_DEPS)
+
+clean.lint:	$(CLEAN_LINT_DEPS)
+
+install:	$(INSTALL_DEPS)
+
+#
+#	Include common targets.
+#
+include $(UTSBASE)/sparc/Makefile.targ
--- a/usr/src/uts/sparc/ip/Makefile	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/sparc/ip/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# 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.
@@ -20,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
@@ -69,7 +68,7 @@
 # swrand as it needs random numbers early on during boot before
 # kCF subsystem can load swrand.
 #
-LDFLAGS		+= -dy -Nmisc/md5 -Ncrypto/swrand
+LDFLAGS		+= -dy -Nmisc/md5 -Ncrypto/swrand -Nmisc/hook -Nmisc/neti 
 
 #
 #	Default build targets.
--- a/usr/src/uts/sparc/ipf/Makefile	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/sparc/ipf/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -1,3 +1,23 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
@@ -46,7 +66,7 @@
 CFLAGS += $(CCVERBOSE)
 CPPFLAGS += -DIPFILTER_LKM -DIPFILTER_LOG -DIPFILTER_LOOKUP 
 CPPFLAGS += -DSUNDDI -DSOLARIS2=$(MINOR:sh) -DIRE_ILL_CN -DUSE_INET6
-LDFLAGS += -dy -Ndrv/ip -Ndrv/pfil -Nmisc/md5
+LDFLAGS += -dy -Ndrv/ip -Nmisc/md5 -Nmisc/neti
 
 INC_PATH += -I$(UTSBASE)/common/inet/ipf
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/sparc/neti/Makefile	Fri Oct 20 16:37:58 2006 -0700
@@ -0,0 +1,90 @@
+#
+# 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
+#
+#
+# uts/sparc/neti/Makefile
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+#
+#	This makefile drives the production of the neti driver kernel module.
+#
+#	SPARC implementation architecture dependent
+#
+
+#
+#	Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE	= ../..
+
+#
+#	Define the module and object file sets.
+#
+MODULE		= neti
+OBJECTS		= $(NETI_OBJS:%=$(OBJS_DIR)/%)
+LINTS		= $(NETI_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE	= $(ROOT_MISC_DIR)/$(MODULE)
+
+#
+#	Include common rules.
+#
+include $(UTSBASE)/sparc/Makefile.sparc
+
+#
+#	Define targets
+#
+ALL_TARGET	= $(BINARY)
+LINT_TARGET	= $(MODULE).lint
+INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOTLINK)
+
+#
+# lint pass one enforcement
+#
+CFLAGS += $(CCVERBOSE)
+
+LDFLAGS		+= -dy -Nmisc/hook
+
+#
+#	Default build targets.
+#
+.KEEP_STATE:
+
+def:		$(DEF_DEPS)
+
+all:		$(ALL_DEPS)
+
+clean:		$(CLEAN_DEPS)
+
+clobber:	$(CLOBBER_DEPS)
+
+lint:		$(LINT_DEPS)
+
+modlintlib:	$(MODLINTLIB_DEPS)
+
+clean.lint:	$(CLEAN_LINT_DEPS)
+
+install:	$(INSTALL_DEPS)
+
+#
+#	Include common targets.
+#
+include $(UTSBASE)/sparc/Makefile.targ
--- a/usr/src/uts/sparc/os/device_policy	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/sparc/os/device_policy	Fri Oct 20 16:37:58 2006 -0700
@@ -90,5 +90,4 @@
 # IP Filter
 #
 ipf             read_priv_set=sys_net_config    write_priv_set=sys_net_config
-pfil            read_priv_set=net_rawaccess     write_priv_set=net_rawaccess
 
--- a/usr/src/uts/sparc/os/minor_perm	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/sparc/os/minor_perm	Fri Oct 20 16:37:58 2006 -0700
@@ -136,7 +136,6 @@
 cryptoadm:cryptoadm 0644 root sys
 crypto:crypto 0666 root sys
 ipf:* 0666 root sys
-pfil:* 0666 root sys
 bl:* 0666 root sys
 sctp:* 0666 root sys
 sctp6:* 0666 root sys
--- a/usr/src/uts/sparc/os/name_to_major	Fri Oct 20 16:24:25 2006 -0700
+++ b/usr/src/uts/sparc/os/name_to_major	Fri Oct 20 16:37:58 2006 -0700
@@ -175,7 +175,6 @@
 pool 226
 zcons 227
 ipf 228
-pfil 229
 ctsmc 230
 bl 231
 ibd 232
--- a/usr/src/uts/sparc/pfil/Makefile	Fri Oct 20 16:24:25 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-#
-# 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 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#ident	"%Z%%M%	%I%	%E% SMI"
-#
-# uts/sparc/pfil/Makefile
-#
-#	This makefile drives the production of the pfil driver 
-#	kernel module.
-#
-#	sparc architecture dependent
-#
-
-#
-#	Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE	= ../..
-
-#
-#	Define the module and object file sets.
-#
-MODULE		= pfil
-OBJECTS		= $(PFIL_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(PFIL_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_DRV_DIR)/$(MODULE)
-ROOTLINK	= $(ROOT_STRMOD_DIR)/$(MODULE)
-CONF_SRCDIR	= $(UTSBASE)/common/inet/pfil
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sparc/Makefile.sparc
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(BINARY) $(SRC_CONFFILE)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOTLINK) $(ROOT_CONFFILE)
-
-#
-# lint pass one enforcement and OS version
-#
-MINOR=    echo $(RELEASE) | cut -d. -f2
-CFLAGS += $(CCVERBOSE)
-CPPFLAGS +=  -DSUNDDI -DSOLARIS2=$(MINOR:sh) -DIRE_ILL_CN -DSOLARIS -DUSE_INET6
-LDFLAGS += -dy -Ndrv/ip
-
-#
-#	Default build targets.
-#
-.KEEP_STATE:
-
-def:		$(DEF_DEPS)
-
-all:		$(ALL_DEPS)
-
-clean:		$(CLEAN_DEPS)
-
-clobber:	$(CLOBBER_DEPS)
-
-lint:		$(LINT_DEPS)
-
-modlintlib:	$(MODLINTLIB_DEPS) lint64
-
-clean.lint:	$(CLEAN_LINT_DEPS)
-
-install:	$(INSTALL_DEPS)
-
-$(ROOTLINK):	$(ROOT_STRMOD_DIR) $(ROOTMODULE)
-	-$(RM) $@; ln $(ROOTMODULE) $@
-
-#
-#	Include common targets.
-#
-include $(UTSBASE)/sparc/Makefile.targ