summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authordr146992 <none@none>2006-10-20 16:37:58 -0700
committerdr146992 <none@none>2006-10-20 16:37:58 -0700
commit381a2a9a387f449fab7d0c7e97c4184c26963abf (patch)
tree9beb8c59e549aba6f888d2adc733dae7e248d9e2 /usr/src
parentf273041ff6419d6156c10c02bb1a527bfcfdc457 (diff)
downloadillumos-joyent-381a2a9a387f449fab7d0c7e97c4184c26963abf.tar.gz
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 --HG-- rename : usr/src/cmd/ipf/etc/pfil.ap.sh => deleted_files/usr/src/cmd/ipf/etc/pfil.ap.sh rename : usr/src/cmd/ipf/pfild/Makefile => deleted_files/usr/src/cmd/ipf/pfild/Makefile rename : usr/src/cmd/ipf/pfild/pfild.c => deleted_files/usr/src/cmd/ipf/pfild/pfild.c rename : usr/src/cmd/ipf/pfild/vas.c => deleted_files/usr/src/cmd/ipf/pfild/vas.c rename : usr/src/cmd/ipf/svc/pfil => deleted_files/usr/src/cmd/ipf/svc/pfil rename : usr/src/cmd/ipf/svc/pfil.xml => deleted_files/usr/src/cmd/ipf/svc/pfil.xml rename : usr/src/uts/common/inet/pfil/compat.h => deleted_files/usr/src/uts/common/inet/pfil/compat.h rename : usr/src/uts/common/inet/pfil/ndd.c => deleted_files/usr/src/uts/common/inet/pfil/ndd.c rename : usr/src/uts/common/inet/pfil/os.h => deleted_files/usr/src/uts/common/inet/pfil/os.h rename : usr/src/uts/common/inet/pfil/pfil.c => deleted_files/usr/src/uts/common/inet/pfil/pfil.c rename : usr/src/uts/common/inet/pfil/pfil.conf => deleted_files/usr/src/uts/common/inet/pfil/pfil.conf rename : usr/src/uts/common/inet/pfil/pfil.h => deleted_files/usr/src/uts/common/inet/pfil/pfil.h rename : usr/src/uts/common/inet/pfil/pfild.h => deleted_files/usr/src/uts/common/inet/pfil/pfild.h rename : usr/src/uts/common/inet/pfil/pfildrv.c => deleted_files/usr/src/uts/common/inet/pfil/pfildrv.c rename : usr/src/uts/common/inet/pfil/pfilstream.c => deleted_files/usr/src/uts/common/inet/pfil/pfilstream.c rename : usr/src/uts/common/inet/pfil/pkt.c => deleted_files/usr/src/uts/common/inet/pfil/pkt.c rename : usr/src/uts/common/inet/pfil/qif.c => deleted_files/usr/src/uts/common/inet/pfil/qif.c rename : usr/src/uts/common/inet/pfil/qif.h => deleted_files/usr/src/uts/common/inet/pfil/qif.h rename : usr/src/uts/intel/pfil/Makefile => deleted_files/usr/src/uts/intel/pfil/Makefile rename : usr/src/uts/sparc/pfil/Makefile => deleted_files/usr/src/uts/sparc/pfil/Makefile rename : usr/src/uts/common/inet/pfil/misc.c => usr/src/uts/common/inet/ipf/misc.c
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/devfsadm/misc_link.c2
-rw-r--r--usr/src/cmd/ipf/Makefile24
-rw-r--r--usr/src/cmd/ipf/etc/Makefile25
-rw-r--r--usr/src/cmd/ipf/etc/pfil.ap.sh69
-rw-r--r--usr/src/cmd/ipf/lib/common/getifname.c29
-rw-r--r--usr/src/cmd/ipf/lib/common/getsumd.c17
-rw-r--r--usr/src/cmd/ipf/pfild/Makefile37
-rw-r--r--usr/src/cmd/ipf/pfild/pfild.c616
-rw-r--r--usr/src/cmd/ipf/pfild/vas.c1258
-rw-r--r--usr/src/cmd/ipf/svc/Makefile26
-rw-r--r--usr/src/cmd/ipf/svc/ipfilter49
-rw-r--r--usr/src/cmd/ipf/svc/ipfilter.xml31
-rwxr-xr-xusr/src/cmd/ipf/svc/pfil43
-rw-r--r--usr/src/cmd/ipf/svc/pfil.xml86
-rw-r--r--usr/src/cmd/ipf/tools/ip_fil.c12
-rw-r--r--usr/src/cmd/ipf/tools/ipf_y.y26
-rw-r--r--usr/src/cmd/mdb/Makefile.common2
-rw-r--r--usr/src/cmd/mdb/common/modules/arp/arp.c2
-rw-r--r--usr/src/cmd/mdb/common/modules/hook/hook.c252
-rw-r--r--usr/src/cmd/mdb/common/modules/neti/neti.c103
-rw-r--r--usr/src/cmd/mdb/intel/amd64/hook/Makefile35
-rw-r--r--usr/src/cmd/mdb/intel/amd64/neti/Makefile35
-rw-r--r--usr/src/cmd/mdb/intel/ia32/hook/Makefile (renamed from usr/src/uts/common/inet/pfil/pfil.conf)10
-rw-r--r--usr/src/cmd/mdb/intel/ia32/neti/Makefile34
-rw-r--r--usr/src/cmd/mdb/sparc/v9/hook/Makefile35
-rw-r--r--usr/src/cmd/mdb/sparc/v9/neti/Makefile35
-rw-r--r--usr/src/cmd/svc/prophist/prophist.SUNWcsr10
-rw-r--r--usr/src/cmd/svc/seed/Makefile3
-rw-r--r--usr/src/cmd/svc/seed/inc.flg8
-rw-r--r--usr/src/lib/libsecdb/exec_attr.txt1
-rw-r--r--usr/src/pkgdefs/SUNWckr/prototype_i3864
-rw-r--r--usr/src/pkgdefs/SUNWckr/prototype_sparc2
-rw-r--r--usr/src/pkgdefs/SUNWhea/prototype_com6
-rw-r--r--usr/src/pkgdefs/SUNWipfr/prototype_com24
-rw-r--r--usr/src/pkgdefs/SUNWipfr/prototype_i38628
-rw-r--r--usr/src/pkgdefs/SUNWipfr/prototype_sparc26
-rw-r--r--usr/src/pkgdefs/SUNWipfu/prototype_com27
-rw-r--r--usr/src/pkgdefs/SUNWipfu/prototype_i38622
-rw-r--r--usr/src/pkgdefs/SUNWipfu/prototype_sparc22
-rw-r--r--usr/src/pkgdefs/SUNWmdb/prototype_i3864
-rw-r--r--usr/src/pkgdefs/SUNWmdb/prototype_sparc2
-rw-r--r--usr/src/pkgdefs/SUNWmdbr/prototype_i3864
-rw-r--r--usr/src/pkgdefs/SUNWmdbr/prototype_sparc2
-rw-r--r--usr/src/tools/scripts/bfu.sh52
-rw-r--r--usr/src/uts/common/Makefile.files14
-rw-r--r--usr/src/uts/common/Makefile.rules3
-rw-r--r--usr/src/uts/common/conf/param.c5
-rw-r--r--usr/src/uts/common/inet/Makefile11
-rw-r--r--usr/src/uts/common/inet/arp/arp.c131
-rw-r--r--usr/src/uts/common/inet/arp/arp_netinfo.c338
-rw-r--r--usr/src/uts/common/inet/arp/arpddi.c46
-rw-r--r--usr/src/uts/common/inet/arp_impl.h72
-rw-r--r--usr/src/uts/common/inet/ip.h151
-rw-r--r--usr/src/uts/common/inet/ip/ip.c444
-rw-r--r--usr/src/uts/common/inet/ip/ip6.c334
-rw-r--r--usr/src/uts/common/inet/ip/ip_ftable.c3
-rw-r--r--usr/src/uts/common/inet/ip/ip_if.c318
-rw-r--r--usr/src/uts/common/inet/ip/ip_multi.c19
-rw-r--r--usr/src/uts/common/inet/ip/ip_ndp.c27
-rw-r--r--usr/src/uts/common/inet/ip/ip_netinfo.c1321
-rw-r--r--usr/src/uts/common/inet/ip6.h2
-rw-r--r--usr/src/uts/common/inet/ip_if.h4
-rw-r--r--usr/src/uts/common/inet/ip_impl.h17
-rw-r--r--usr/src/uts/common/inet/ip_ire.h3
-rw-r--r--usr/src/uts/common/inet/ip_netinfo.h52
-rw-r--r--usr/src/uts/common/inet/ipf/fil.c202
-rw-r--r--usr/src/uts/common/inet/ipf/ip_auth.c49
-rw-r--r--usr/src/uts/common/inet/ipf/ip_fil_solaris.c1261
-rw-r--r--usr/src/uts/common/inet/ipf/ip_log.c64
-rw-r--r--usr/src/uts/common/inet/ipf/ip_nat.c369
-rw-r--r--usr/src/uts/common/inet/ipf/ip_proxy.c25
-rw-r--r--usr/src/uts/common/inet/ipf/ip_state.c72
-rw-r--r--usr/src/uts/common/inet/ipf/misc.c (renamed from usr/src/uts/common/inet/pfil/misc.c)25
-rw-r--r--usr/src/uts/common/inet/ipf/netinet/ip_compat.h65
-rw-r--r--usr/src/uts/common/inet/ipf/netinet/ip_fil.h12
-rw-r--r--usr/src/uts/common/inet/ipf/netinet/ip_irc_pxy.c2
-rw-r--r--usr/src/uts/common/inet/ipf/netinet/ip_nat.h8
-rw-r--r--usr/src/uts/common/inet/ipf/netinet/ip_state.h2
-rw-r--r--usr/src/uts/common/inet/ipf/solaris.c86
-rw-r--r--usr/src/uts/common/inet/pfil/compat.h78
-rw-r--r--usr/src/uts/common/inet/pfil/ndd.c442
-rw-r--r--usr/src/uts/common/inet/pfil/os.h40
-rw-r--r--usr/src/uts/common/inet/pfil/pfil.c358
-rw-r--r--usr/src/uts/common/inet/pfil/pfil.h141
-rw-r--r--usr/src/uts/common/inet/pfil/pfild.h65
-rw-r--r--usr/src/uts/common/inet/pfil/pfildrv.c1171
-rw-r--r--usr/src/uts/common/inet/pfil/pfilstream.c761
-rw-r--r--usr/src/uts/common/inet/pfil/pkt.c345
-rw-r--r--usr/src/uts/common/inet/pfil/qif.c859
-rw-r--r--usr/src/uts/common/inet/pfil/qif.h203
-rw-r--r--usr/src/uts/common/inet/tcp.h3
-rw-r--r--usr/src/uts/common/inet/tcp/tcp.c160
-rw-r--r--usr/src/uts/common/inet/tcp/tcp_fusion.c108
-rw-r--r--usr/src/uts/common/inet/udp/udp.c12
-rw-r--r--usr/src/uts/common/io/bge/bge_send.c11
-rw-r--r--usr/src/uts/common/io/hook.c685
-rw-r--r--usr/src/uts/common/io/neti.c509
-rw-r--r--usr/src/uts/common/io/stream.c24
-rw-r--r--usr/src/uts/common/sys/Makefile5
-rw-r--r--usr/src/uts/common/sys/condvar_impl.h56
-rw-r--r--usr/src/uts/common/sys/hook.h115
-rw-r--r--usr/src/uts/common/sys/hook_event.h100
-rw-r--r--usr/src/uts/common/sys/hook_impl.h136
-rw-r--r--usr/src/uts/common/sys/neti.h197
-rw-r--r--usr/src/uts/common/sys/queue.h667
-rw-r--r--usr/src/uts/common/sys/stream.h4
-rw-r--r--usr/src/uts/intel/Makefile.intel.shared3
-rw-r--r--usr/src/uts/intel/arp/Makefile9
-rw-r--r--usr/src/uts/intel/hook/Makefile (renamed from usr/src/uts/intel/pfil/Makefile)29
-rw-r--r--usr/src/uts/intel/ip/Makefile9
-rw-r--r--usr/src/uts/intel/ipf/Makefile22
-rw-r--r--usr/src/uts/intel/neti/Makefile86
-rw-r--r--usr/src/uts/intel/os/device_policy1
-rw-r--r--usr/src/uts/intel/os/minor_perm1
-rw-r--r--usr/src/uts/intel/os/name_to_major1
-rw-r--r--usr/src/uts/sparc/Makefile.sparc.shared4
-rw-r--r--usr/src/uts/sparc/arp/Makefile9
-rw-r--r--usr/src/uts/sparc/hook/Makefile88
-rw-r--r--usr/src/uts/sparc/ip/Makefile9
-rw-r--r--usr/src/uts/sparc/ipf/Makefile22
-rw-r--r--usr/src/uts/sparc/neti/Makefile (renamed from usr/src/uts/sparc/pfil/Makefile)35
-rw-r--r--usr/src/uts/sparc/os/device_policy1
-rw-r--r--usr/src/uts/sparc/os/minor_perm1
-rw-r--r--usr/src/uts/sparc/os/name_to_major1
124 files changed, 8398 insertions, 7885 deletions
diff --git a/usr/src/cmd/devfsadm/misc_link.c b/usr/src/cmd/devfsadm/misc_link.c
index 0766c3dc28..4ad6e87777 100644
--- a/usr/src/cmd/devfsadm/misc_link.c
+++ b/usr/src/cmd/devfsadm/misc_link.c
@@ -110,7 +110,7 @@ static devfsadm_create_t misc_cbt[] = {
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,
},
diff --git a/usr/src/cmd/ipf/Makefile b/usr/src/cmd/ipf/Makefile
index b5376faba1..953beb9fec 100644
--- a/usr/src/cmd/ipf/Makefile
+++ b/usr/src/cmd/ipf/Makefile
@@ -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=
diff --git a/usr/src/cmd/ipf/etc/Makefile b/usr/src/cmd/ipf/etc/Makefile
index 0971010338..afe39fa704 100644
--- a/usr/src/cmd/ipf/etc/Makefile
+++ b/usr/src/cmd/ipf/etc/Makefile
@@ -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
diff --git a/usr/src/cmd/ipf/etc/pfil.ap.sh b/usr/src/cmd/ipf/etc/pfil.ap.sh
deleted file mode 100644
index 6bf62c9ad3..0000000000
--- a/usr/src/cmd/ipf/etc/pfil.ap.sh
+++ /dev/null
@@ -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
-
diff --git a/usr/src/cmd/ipf/lib/common/getifname.c b/usr/src/cmd/ipf/lib/common/getifname.c
index a42a4e089b..ec3ae926b2 100644
--- a/usr/src/cmd/ipf/lib/common/getifname.c
+++ b/usr/src/cmd/ipf/lib/common/getifname.c
@@ -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 @@ struct ifnet *ptr;
# 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 @@ struct ifnet *ptr;
# 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 @@ struct ifnet *ptr;
sprintf(buf + strlen(buf), "%d", netif.if_unit % 10000);
return strdup(buf);
# endif
-#endif
}
diff --git a/usr/src/cmd/ipf/lib/common/getsumd.c b/usr/src/cmd/ipf/lib/common/getsumd.c
index 346c445ff8..bcf0945497 100644
--- a/usr/src/cmd/ipf/lib/common/getsumd.c
+++ b/usr/src/cmd/ipf/lib/common/getsumd.c
@@ -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 @@ u_32_t sum;
{
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;
}
diff --git a/usr/src/cmd/ipf/pfild/Makefile b/usr/src/cmd/ipf/pfild/Makefile
deleted file mode 100644
index 0b14c9f50b..0000000000
--- a/usr/src/cmd/ipf/pfild/Makefile
+++ /dev/null
@@ -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
diff --git a/usr/src/cmd/ipf/pfild/pfild.c b/usr/src/cmd/ipf/pfild/pfild.c
deleted file mode 100644
index f811694340..0000000000
--- a/usr/src/cmd/ipf/pfild/pfild.c
+++ /dev/null
@@ -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 */
-}
diff --git a/usr/src/cmd/ipf/pfild/vas.c b/usr/src/cmd/ipf/pfild/vas.c
deleted file mode 100644
index 25d200a3d7..0000000000
--- a/usr/src/cmd/ipf/pfild/vas.c
+++ /dev/null
@@ -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
diff --git a/usr/src/cmd/ipf/svc/Makefile b/usr/src/cmd/ipf/svc/Makefile
index ec1c98c92d..403db5ce4e 100644
--- a/usr/src/cmd/ipf/svc/Makefile
+++ b/usr/src/cmd/ipf/svc/Makefile
@@ -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
diff --git a/usr/src/cmd/ipf/svc/ipfilter b/usr/src/cmd/ipf/svc/ipfilter
index 97a7d704d8..a34efe3781 100644
--- a/usr/src/cmd/ipf/svc/ipfilter
+++ b/usr/src/cmd/ipf/svc/ipfilter
@@ -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 @@ if [ -f $PIDFILE ] ; then
else
pid=`pgrep ipmon`
fi
-pfildpid=`pgrep pfild`
logmsg()
{
@@ -30,31 +49,9 @@ logmsg()
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 @@ load_ipf() {
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_ipf() {
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_ipnat() {
load_ippool() {
if [ -r ${IPPOOLCONF} ]; then
- checkpfil
ippool -F >/dev/null
ippool -f ${IPPOOLCONF} >/dev/null
if [ $? != 0 ]; then
@@ -116,9 +110,7 @@ load_ippool() {
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 @@ case "$1" in
;;
stop)
- [ -n "$pfildpid" ] && kill -TERM $pfildpid
[ -n "$pid" ] && kill -TERM $pid
;;
diff --git a/usr/src/cmd/ipf/svc/ipfilter.xml b/usr/src/cmd/ipf/svc/ipfilter.xml
index 81fddd2809..f9d34ea7d9 100644
--- a/usr/src/cmd/ipf/svc/ipfilter.xml
+++ b/usr/src/cmd/ipf/svc/ipfilter.xml
@@ -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'
diff --git a/usr/src/cmd/ipf/svc/pfil b/usr/src/cmd/ipf/svc/pfil
deleted file mode 100755
index b2db444ffe..0000000000
--- a/usr/src/cmd/ipf/svc/pfil
+++ /dev/null
@@ -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
diff --git a/usr/src/cmd/ipf/svc/pfil.xml b/usr/src/cmd/ipf/svc/pfil.xml
deleted file mode 100644
index 7d69af24b2..0000000000
--- a/usr/src/cmd/ipf/svc/pfil.xml
+++ /dev/null
@@ -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>
diff --git a/usr/src/cmd/ipf/tools/ip_fil.c b/usr/src/cmd/ipf/tools/ip_fil.c
index 0011968b9a..4aaa9935be 100644
--- a/usr/src/cmd/ipf/tools/ip_fil.c
+++ b/usr/src/cmd/ipf/tools/ip_fil.c
@@ -410,7 +410,7 @@ int mode;
if (!(mode & FWRITE))
error = EPERM;
else {
- frsync(NULL);
+ frsync(IPFSYNC_RESYNC, IPFSYNC_RESYNC, NULL, NULL);
}
break;
default :
@@ -455,7 +455,7 @@ void *ifp;
f->fr_ifa = (void *)-1;
#endif
RWLOCK_EXIT(&ipf_mutex);
- fr_natsync(ifp);
+ fr_natifpsync(IPFSYNC_OLDIFP, ifp, NULL);
}
@@ -614,7 +614,7 @@ int v;
*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 @@ int dst;
}
-void frsync(ifp)
-void *ifp;
+void frsync(command, version, nic, data)
+int command, version;
+void *nic;
+char *data;
{
return;
}
diff --git a/usr/src/cmd/ipf/tools/ipf_y.y b/usr/src/cmd/ipf/tools/ipf_y.y
index 93e6d27da9..940790493a 100644
--- a/usr/src/cmd/ipf/tools/ipf_y.y
+++ b/usr/src/cmd/ipf/tools/ipf_y.y
@@ -177,6 +177,7 @@ static int set_ipv6_addr = 0;
%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 @@ line: xx rule { while ((fr = frtop) != NULL) {
resetlexer();
}
| YY_COMMENT
+ | set
;
xx: { newrule(); }
@@ -210,6 +212,28 @@ assigning:
'=' { 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 @@ static struct wordtab ipfwords[95] = {
{ "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 @@ static struct wordtab ipfwords[95] = {
{ "route-to", IPFY_ROUTETO },
{ "sec-class", IPFY_SECCLASS },
{ "set-tag", IPFY_SETTAG },
+ { "set", IPFY_SET },
{ "skip", IPFY_SKIP },
{ "short", IPFY_SHORT },
{ "state", IPFY_STATE },
diff --git a/usr/src/cmd/mdb/Makefile.common b/usr/src/cmd/mdb/Makefile.common
index 329176e35b..4f2adfeb9b 100644
--- a/usr/src/cmd/mdb/Makefile.common
+++ b/usr/src/cmd/mdb/Makefile.common
@@ -57,6 +57,8 @@ COMMON_MODULES_KVM = \
crypto \
dtrace \
genunix \
+ hook \
+ neti \
ip \
ipc \
ipp \
diff --git a/usr/src/cmd/mdb/common/modules/arp/arp.c b/usr/src/cmd/mdb/common/modules/arp/arp.c
index 06bd8887e0..c02c20a268 100644
--- a/usr/src/cmd/mdb/common/modules/arp/arp.c
+++ b/usr/src/cmd/mdb/common/modules/arp/arp.c
@@ -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>
diff --git a/usr/src/cmd/mdb/common/modules/hook/hook.c b/usr/src/cmd/mdb/common/modules/hook/hook.c
new file mode 100644
index 0000000000..d9ab29eb24
--- /dev/null
+++ b/usr/src/cmd/mdb/common/modules/hook/hook.c
@@ -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);
+}
diff --git a/usr/src/cmd/mdb/common/modules/neti/neti.c b/usr/src/cmd/mdb/common/modules/neti/neti.c
new file mode 100644
index 0000000000..788099b048
--- /dev/null
+++ b/usr/src/cmd/mdb/common/modules/neti/neti.c
@@ -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);
+}
diff --git a/usr/src/cmd/mdb/intel/amd64/hook/Makefile b/usr/src/cmd/mdb/intel/amd64/hook/Makefile
new file mode 100644
index 0000000000..457244bd5d
--- /dev/null
+++ b/usr/src/cmd/mdb/intel/amd64/hook/Makefile
@@ -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
diff --git a/usr/src/cmd/mdb/intel/amd64/neti/Makefile b/usr/src/cmd/mdb/intel/amd64/neti/Makefile
new file mode 100644
index 0000000000..141c284897
--- /dev/null
+++ b/usr/src/cmd/mdb/intel/amd64/neti/Makefile
@@ -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
diff --git a/usr/src/uts/common/inet/pfil/pfil.conf b/usr/src/cmd/mdb/intel/ia32/hook/Makefile
index 1cf479a0d6..fb06c57cec 100644
--- a/usr/src/uts/common/inet/pfil/pfil.conf
+++ b/usr/src/cmd/mdb/intel/ia32/hook/Makefile
@@ -22,7 +22,13 @@
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
+#ident "%Z%%M% %I% %E% SMI"
-name="pfil" parent="pseudo" instance=0;
+MODULE = hook.so
+MDBTGT = kvm
+MODSRCS = hook.c
+
+include ../../../../Makefile.cmd
+include ../../Makefile.ia32
+include ../../../Makefile.module
diff --git a/usr/src/cmd/mdb/intel/ia32/neti/Makefile b/usr/src/cmd/mdb/intel/ia32/neti/Makefile
new file mode 100644
index 0000000000..370d3ba2d3
--- /dev/null
+++ b/usr/src/cmd/mdb/intel/ia32/neti/Makefile
@@ -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
diff --git a/usr/src/cmd/mdb/sparc/v9/hook/Makefile b/usr/src/cmd/mdb/sparc/v9/hook/Makefile
new file mode 100644
index 0000000000..1c2c6453a9
--- /dev/null
+++ b/usr/src/cmd/mdb/sparc/v9/hook/Makefile
@@ -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
diff --git a/usr/src/cmd/mdb/sparc/v9/neti/Makefile b/usr/src/cmd/mdb/sparc/v9/neti/Makefile
new file mode 100644
index 0000000000..8879100579
--- /dev/null
+++ b/usr/src/cmd/mdb/sparc/v9/neti/Makefile
@@ -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
diff --git a/usr/src/cmd/svc/prophist/prophist.SUNWcsr b/usr/src/cmd/svc/prophist/prophist.SUNWcsr
index 44978057e8..77bf3a49a8 100644
--- a/usr/src/cmd/svc/prophist/prophist.SUNWcsr
+++ b/usr/src/cmd/svc/prophist/prophist.SUNWcsr
@@ -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 @@ prophist_adddpt svc:/network/ntp ntp_multi-user optional_all none \
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 \
diff --git a/usr/src/cmd/svc/seed/Makefile b/usr/src/cmd/svc/seed/Makefile
index 5d6a2e5a04..37da95d671 100644
--- a/usr/src/cmd/svc/seed/Makefile
+++ b/usr/src/cmd/svc/seed/Makefile
@@ -75,8 +75,7 @@ GLOBAL_ZONE_DESCRIPTIONS = \
../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
diff --git a/usr/src/cmd/svc/seed/inc.flg b/usr/src/cmd/svc/seed/inc.flg
index c8adc2a41f..8224abb7f3 100644
--- a/usr/src/cmd/svc/seed/inc.flg
+++ b/usr/src/cmd/svc/seed/inc.flg
@@ -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/rpcbind/bind.xml
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
diff --git a/usr/src/lib/libsecdb/exec_attr.txt b/usr/src/lib/libsecdb/exec_attr.txt
index 6cbee3ea1f..07dc34f7bb 100644
--- a/usr/src/lib/libsecdb/exec_attr.txt
+++ b/usr/src/lib/libsecdb/exec_attr.txt
@@ -107,7 +107,6 @@ IP Filter Management:solaris:cmd:::/usr/sbin/ipmon:privs=sys_net_config
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
diff --git a/usr/src/pkgdefs/SUNWckr/prototype_i386 b/usr/src/pkgdefs/SUNWckr/prototype_i386
index f3a0b360da..839daf5e94 100644
--- a/usr/src/pkgdefs/SUNWckr/prototype_i386
+++ b/usr/src/pkgdefs/SUNWckr/prototype_i386
@@ -159,6 +159,7 @@ l none kernel/misc/des=../../kernel/crypto/des
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/kmdbmod 755 root sys
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 @@ l none kernel/misc/amd64/des=../../../kernel/crypto/amd64/des
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/kmdbmod 755 root sys
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
diff --git a/usr/src/pkgdefs/SUNWckr/prototype_sparc b/usr/src/pkgdefs/SUNWckr/prototype_sparc
index 062109cbf3..a5a01f4126 100644
--- a/usr/src/pkgdefs/SUNWckr/prototype_sparc
+++ b/usr/src/pkgdefs/SUNWckr/prototype_sparc
@@ -168,6 +168,7 @@ l none kernel/misc/sparcv9/des=../../../kernel/crypto/sparcv9/des
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/kcf 755 root sys
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
diff --git a/usr/src/pkgdefs/SUNWhea/prototype_com b/usr/src/pkgdefs/SUNWhea/prototype_com
index 33ecce0f6f..4331dbb4d1 100644
--- a/usr/src/pkgdefs/SUNWhea/prototype_com
+++ b/usr/src/pkgdefs/SUNWhea/prototype_com
@@ -139,6 +139,7 @@ f none usr/include/inet/ip_if.h 644 root bin
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/fstyp.h 644 root bin
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/netconfig.h 644 root bin
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/psw.h 644 root bin
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
diff --git a/usr/src/pkgdefs/SUNWipfr/prototype_com b/usr/src/pkgdefs/SUNWipfr/prototype_com
index 227230ca02..a0d550faba 100644
--- a/usr/src/pkgdefs/SUNWipfr/prototype_com
+++ b/usr/src/pkgdefs/SUNWipfr/prototype_com
@@ -1,4 +1,24 @@
#
+# 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 @@ i i.preserve
#
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/db/ipf 755 root sys
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
diff --git a/usr/src/pkgdefs/SUNWipfr/prototype_i386 b/usr/src/pkgdefs/SUNWipfr/prototype_i386
index 5695a692e2..f745fb3564 100644
--- a/usr/src/pkgdefs/SUNWipfr/prototype_i386
+++ b/usr/src/pkgdefs/SUNWipfr/prototype_i386
@@ -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
diff --git a/usr/src/pkgdefs/SUNWipfr/prototype_sparc b/usr/src/pkgdefs/SUNWipfr/prototype_sparc
index 60ff96c3c5..d082baa2bd 100644
--- a/usr/src/pkgdefs/SUNWipfr/prototype_sparc
+++ b/usr/src/pkgdefs/SUNWipfr/prototype_sparc
@@ -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
#
diff --git a/usr/src/pkgdefs/SUNWipfu/prototype_com b/usr/src/pkgdefs/SUNWipfu/prototype_com
index cf4f0f6d32..26372d31d0 100644
--- a/usr/src/pkgdefs/SUNWipfu/prototype_com
+++ b/usr/src/pkgdefs/SUNWipfu/prototype_com
@@ -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 755 root bin
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/ipfstat=../../usr/lib/isaexec
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
diff --git a/usr/src/pkgdefs/SUNWipfu/prototype_i386 b/usr/src/pkgdefs/SUNWipfu/prototype_i386
index eada1517e0..4be9267375 100644
--- a/usr/src/pkgdefs/SUNWipfu/prototype_i386
+++ b/usr/src/pkgdefs/SUNWipfu/prototype_i386
@@ -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"
diff --git a/usr/src/pkgdefs/SUNWipfu/prototype_sparc b/usr/src/pkgdefs/SUNWipfu/prototype_sparc
index 797561e8c6..543bfb36a4 100644
--- a/usr/src/pkgdefs/SUNWipfu/prototype_sparc
+++ b/usr/src/pkgdefs/SUNWipfu/prototype_sparc
@@ -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"
diff --git a/usr/src/pkgdefs/SUNWmdb/prototype_i386 b/usr/src/pkgdefs/SUNWmdb/prototype_i386
index ff996ca924..b84b6dc728 100644
--- a/usr/src/pkgdefs/SUNWmdb/prototype_i386
+++ b/usr/src/pkgdefs/SUNWmdb/prototype_i386
@@ -53,6 +53,8 @@ f none usr/lib/mdb/kvm/amd64/cpc.so 555 root sys
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/cpc.so 555 root sys
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
diff --git a/usr/src/pkgdefs/SUNWmdb/prototype_sparc b/usr/src/pkgdefs/SUNWmdb/prototype_sparc
index f597cae61d..240d6c0cd4 100644
--- a/usr/src/pkgdefs/SUNWmdb/prototype_sparc
+++ b/usr/src/pkgdefs/SUNWmdb/prototype_sparc
@@ -45,6 +45,8 @@ f none usr/lib/mdb/kvm/sparcv9/crypto.so 555 root sys
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
diff --git a/usr/src/pkgdefs/SUNWmdbr/prototype_i386 b/usr/src/pkgdefs/SUNWmdbr/prototype_i386
index 53758ed816..82cb3fd4d8 100644
--- a/usr/src/pkgdefs/SUNWmdbr/prototype_i386
+++ b/usr/src/pkgdefs/SUNWmdbr/prototype_i386
@@ -34,6 +34,8 @@ f none kernel/kmdb/amd64/cpc 555 root sys
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/cpc 555 root sys
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
diff --git a/usr/src/pkgdefs/SUNWmdbr/prototype_sparc b/usr/src/pkgdefs/SUNWmdbr/prototype_sparc
index bfb6414a25..df345ad032 100644
--- a/usr/src/pkgdefs/SUNWmdbr/prototype_sparc
+++ b/usr/src/pkgdefs/SUNWmdbr/prototype_sparc
@@ -35,6 +35,8 @@ f none kernel/kmdb/sparcv9/crypto 555 root sys
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
diff --git a/usr/src/tools/scripts/bfu.sh b/usr/src/tools/scripts/bfu.sh
index 7494a69102..c1fa6b528c 100644
--- a/usr/src/tools/scripts/bfu.sh
+++ b/usr/src/tools/scripts/bfu.sh
@@ -316,7 +316,6 @@ superfluous_local_zone_files="
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 @@ superfluous_local_zone_files="
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 @@ smf_obsolete_rc_files="
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 @@ smf_obsolete_rc_files="
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 @@ smf_obsolete_manifests="
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_renamed_manifests="
smf_obsolete_methods="
lib/svc/method/print-server
lib/svc/method/svc-volfs
+ lib/svc/method/pfil
"
smf_cleanup () {
@@ -1706,47 +1704,32 @@ EOFA
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 @@ mondo_loop() {
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
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index 70b93c0e10..e8dc6b6f60 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -430,7 +430,7 @@ TOKENMT_OBJS += tokenmt.o tokenmtddi.o
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 @@ IP_SCTP_OBJS = sctp_crc32.o sctp.o sctp_opt_data.o sctp_output.o \
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 @@ IP_OBJS += igmp.o ip.o ip6.o ip6_asp.o ip6_if.o ip6_ire.o ip6_rts.o \
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 @@ LDTERM_OBJS += ldterm.o uwidth.o
PCKT_OBJS += pckt.o
-PFMOD_OBJS += pfmod.o
+PFMOD_OBJS += pfmod.o
PTEM_OBJS += ptem.o
@@ -1242,10 +1246,8 @@ PHX_OBJS += phx.o
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
diff --git a/usr/src/uts/common/Makefile.rules b/usr/src/uts/common/Makefile.rules
index 82b1840f00..64994fabb1 100644
--- a/usr/src/uts/common/Makefile.rules
+++ b/usr/src/uts/common/Makefile.rules
@@ -370,9 +370,8 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/common/inet/tcp/%.c
$(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
diff --git a/usr/src/uts/common/conf/param.c b/usr/src/uts/common/conf/param.c
index 6519a36a30..c236d570be 100644
--- a/usr/src/uts/common/conf/param.c
+++ b/usr/src/uts/common/conf/param.c
@@ -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.
diff --git a/usr/src/uts/common/inet/Makefile b/usr/src/uts/common/inet/Makefile
index 7b0cdbc607..8f6c111896 100644
--- a/usr/src/uts/common/inet/Makefile
+++ b/usr/src/uts/common/inet/Makefile
@@ -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
diff --git a/usr/src/uts/common/inet/arp/arp.c b/usr/src/uts/common/inet/arp/arp.c
index 17c81b9513..97528cf323 100644
--- a/usr/src/uts/common/inet/arp/arp.c
+++ b/usr/src/uts/common/inet/arp/arp.c
@@ -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 @@ struct streamtab arpinfo = {
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_hash_tbl[ARP_HASH_SIZE];
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 @@ static int
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_close(queue_t *q)
*/
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_close(queue_t *q)
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);
- mi_free((char *)arl);
ar->ar_arl = NULL;
+ rw_exit(&arl_g_lock);
+
+ mi_free((char *)arl);
}
/* Let's break the association between an ARL and IP instance */
if (ar->ar_arl_ip_assoc != NULL) {
@@ -1034,6 +1057,17 @@ ar_close(queue_t *q)
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 @@ ar_ll_lookup_by_name(const char *name)
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 @@ ar_ll_init(ar_t *ar, mblk_t *mp)
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_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
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 @@ ar_rput(queue_t *q, mblk_t *mp)
* 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 @@ ar_slifname(queue_t *q, mblk_t *mp_orig)
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 @@ ar_slifname(queue_t *q, mblk_t *mp_orig)
/* 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 @@ ar_slifname(queue_t *q, mblk_t *mp_orig)
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 @@ ar_set_ppa(queue_t *q, mblk_t *mp_orig)
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 @@ ar_xmit(arl_t *arl, uint32_t operation, uint32_t proto, uint32_t plen,
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);
diff --git a/usr/src/uts/common/inet/arp/arp_netinfo.c b/usr/src/uts/common/inet/arp/arp_netinfo.c
new file mode 100644
index 0000000000..49dd1ef78a
--- /dev/null
+++ b/usr/src/uts/common/inet/arp/arp_netinfo.c
@@ -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);
+}
diff --git a/usr/src/uts/common/inet/arp/arpddi.c b/usr/src/uts/common/inet/arp/arpddi.c
index da5052c512..7443d0a9bd 100644
--- a/usr/src/uts/common/inet/arp/arpddi.c
+++ b/usr/src/uts/common/inet/arp/arpddi.c
@@ -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 @@ _info(struct modinfo *modinfop)
{
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);
+}
diff --git a/usr/src/uts/common/inet/arp_impl.h b/usr/src/uts/common/inet/arp_impl.h
index e87fc69ab3..a95a335e7f 100644
--- a/usr/src/uts/common/inet/arp_impl.h
+++ b/usr/src/uts/common/inet/arp_impl.h
@@ -72,8 +72,12 @@ typedef struct arl_s {
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 @@ typedef struct ace_s {
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
diff --git a/usr/src/uts/common/inet/ip.h b/usr/src/uts/common/inet/ip.h
index 672da54818..2fa1281806 100644
--- a/usr/src/uts/common/inet/ip.h
+++ b/usr/src/uts/common/inet/ip.h
@@ -43,6 +43,10 @@ extern "C" {
#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 @@ typedef struct ill_s {
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 timeout_id_t mld_slowtimeout_id;
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 winit_tcp;
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 *,
diff --git a/usr/src/uts/common/inet/ip/ip.c b/usr/src/uts/common/inet/ip/ip.c
index 9547087c94..e0dc4bf667 100644
--- a/usr/src/uts/common/inet/ip/ip.c
+++ b/usr/src/uts/common/inet/ip/ip.c
@@ -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 @@ nv_t *ire_nv_tbl = ire_nv_arr;
/* 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 @@ ip_modclose(ill_t *ill)
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 @@ ip_modclose(ill_t *ill)
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 @@ ip_csum_hdr(ipha_t *ipha)
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 @@ ip_ddi_init(void)
icmp_kstat_init();
ipsec_loader_start();
tnet_init();
+
+ ip_net_init();
+ ipv4_hook_init();
+ ipv6_hook_init();
}
/*
@@ -7200,6 +7230,7 @@ ip_mrtun_forward(ire_t *ire, ill_t *in_ill, mblk_t *mp)
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 @@ ip_mrtun_forward(ire_t *ire, ill_t *in_ill, mblk_t *mp)
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 @@ ip_mrtun_forward(ire_t *ire, ill_t *in_ill, mblk_t *mp)
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 @@ ip_rput_notforus(queue_t **qp, mblk_t *mp, ire_t *ire, ill_t *ill)
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 @@ ip_fast_forward(ire_t *ire, ipaddr_t dst, ill_t *ill, mblk_t *mp)
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 @@ ip_fast_forward(ire_t *ire, ipaddr_t dst, ill_t *ill, mblk_t *mp)
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 @@ ip_input(ill_t *ill, ill_rx_ring_t *ip_ring, mblk_t *mp_chain,
}
}
+ /*
+ * 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 @@ ip_input(ill_t *ill, ill_rx_ring_t *ip_ring, mblk_t *mp_chain,
}
/*
+ * 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 @@ ip_rput_dlpi_writer(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
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 @@ ip_rput_dlpi_writer(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
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 @@ ip_rput_forward(ire_t *ire, ipha_t *ipha, mblk_t *mp, ill_t *in_ill)
#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 @@ ip_rput_forward(ire_t *ire, ipha_t *ipha, mblk_t *mp, ill_t *in_ill)
/* 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 @@ ip_rput_forward(ire_t *ire, ipha_t *ipha, mblk_t *mp, ill_t *in_ill)
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 @@ ip_wput_ire(queue_t *q, mblk_t *mp, ire_t *ire, conn_t *connp, int caller,
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 @@ another:;
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 @@ another:;
(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 @@ broadcast:
}
}
+ 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 @@ broadcast:
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 @@ broadcast:
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 @@ ip_wput_frag(ire_t *ire, mblk_t *mp_orig, ip_pkt_t pkt_type, uint32_t max_frag,
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 @@ ip_wput_frag(ire_t *ire, mblk_t *mp_orig, ip_pkt_t pkt_type, uint32_t max_frag,
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 @@ ip_wput_frag(ire_t *ire, mblk_t *mp_orig, ip_pkt_t pkt_type, uint32_t max_frag,
}
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 @@ ip_wput_local(queue_t *q, ill_t *ill, ipha_t *ipha, mblk_t *mp, ire_t *ire,
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 @@ ip_wput_ipsec_out_v6(queue_t *q, mblk_t *ipsec_mp, ip6_t *ip6h, ill_t *ill,
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 @@ send:
/* 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 @@ ip_wput_ipsec_out(queue_t *q, mblk_t *ipsec_mp, ipha_t *ipha, ill_t *ill,
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 @@ send:
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 @@ send:
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 @@ ip_ioctl_finish(queue_t *q, mblk_t *mp, int err, int mode,
ipif_t *ipif, ipsq_t *ipsq)
{
conn_t *connp = NULL;
+ hook_nic_event_t *info;
if (err == EINPROGRESS)
return;
@@ -25986,6 +26312,26 @@ ip_ioctl_finish(queue_t *q, mblk_t *mp, int err, int mode,
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 @@ ip_xmit_v4(mblk_t *mp, ire_t *ire, ipsec_out_t *io, boolean_t flow_ctl_enabled)
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 @@ ip_xmit_v4(mblk_t *mp, ire_t *ire, ipsec_out_t *io, boolean_t flow_ctl_enabled)
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 @@ ip_xmit_v4(mblk_t *mp, ire_t *ire, ipsec_out_t *io, boolean_t flow_ctl_enabled)
}
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 {
/*
diff --git a/usr/src/uts/common/inet/ip/ip6.c b/usr/src/uts/common/inet/ip/ip6.c
index 2e9cc4afc6..bc4176dbbd 100644
--- a/usr/src/uts/common/inet/ip/ip6.c
+++ b/usr/src/uts/common/inet/ip/ip6.c
@@ -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 @@ static void ip_wput_ire_v6(queue_t *, mblk_t *, ire_t *, int, int,
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 @@ ip_process_rthdr(queue_t *q, mblk_t *mp, ip6_t *ip6h, ip6_rthdr_t *rth,
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 @@ hada_drop:
/*
* 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 @@ ip_rput_v6(queue_t *q, mblk_t *mp)
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 @@ ipsec_early_ah_v6(queue_t *q, mblk_t *first_mp, boolean_t mctl_present,
}
/*
+ * 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 @@ ip_rput_data_v6(queue_t *q, ill_t *inill, mblk_t *mp, ip6_t *ip6h,
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 @@ ip_rput_data_v6(queue_t *q, ill_t *inill, mblk_t *mp, ip6_t *ip6h,
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 @@ ip_rput_data_v6(queue_t *q, ill_t *inill, mblk_t *mp, ip6_t *ip6h,
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 @@ ip_wput_local_v6(queue_t *q, ill_t *ill, ip6_t *ip6h, mblk_t *first_mp,
}
+ 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 @@ ip_wput_ire_v6(queue_t *q, mblk_t *mp, ire_t *ire, int unspec_src,
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;
+ }
+
+ 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);
}
- /*
- * 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 @@ ip_wput_ire_v6(queue_t *q, mblk_t *mp, ire_t *ire, int unspec_src,
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 @@ ip_xmit_v6(mblk_t *mp, ire_t *ire, uint_t flags, conn_t *connp,
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 @@ ip_xmit_v6(mblk_t *mp, ire_t *ire, uint_t flags, conn_t *connp,
}
do {
- boolean_t qos_done = B_FALSE;
+ mblk_t *mp_ip6h;
if (multirt_send) {
irb_t *irb;
@@ -12055,6 +12153,23 @@ ip_xmit_v6(mblk_t *mp, ire_t *ire, uint_t flags, conn_t *connp,
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 @@ ip_xmit_v6(mblk_t *mp, ire_t *ire, uint_t flags, conn_t *connp,
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 @@ ip_xmit_v6(mblk_t *mp, ire_t *ire, uint_t flags, conn_t *connp,
*/
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 @@ ip_xmit_v6(mblk_t *mp, ire_t *ire, uint_t flags, conn_t *connp,
* 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 @@ ip_xmit_v6(mblk_t *mp, ire_t *ire, uint_t flags, conn_t *connp,
* 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 @@ ip_xmit_v6(mblk_t *mp, ire_t *ire, uint_t flags, conn_t *connp,
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;
}
}
diff --git a/usr/src/uts/common/inet/ip/ip_ftable.c b/usr/src/uts/common/inet/ip/ip_ftable.c
index 145f1435b7..ae30aab09b 100644
--- a/usr/src/uts/common/inet/ip/ip_ftable.c
+++ b/usr/src/uts/common/inet/ip/ip_ftable.c
@@ -1293,6 +1293,7 @@ ipfil_sendpkt(const struct sockaddr *dst_addr, mblk_t *mp, uint_t ifindex,
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 @@ ipfil_sendpkt(const struct sockaddr *dst_addr, mblk_t *mp, uint_t ifindex,
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
diff --git a/usr/src/uts/common/inet/ip/ip_if.c b/usr/src/uts/common/inet/ip/ip_if.c
index 583444ce8f..7804fdcb2f 100644
--- a/usr/src/uts/common/inet/ip/ip_if.c
+++ b/usr/src/uts/common/inet/ip/ip_if.c
@@ -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 @@ ill_delete_interface_type(ill_if_t *interface)
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_glist_delete(ill_t *ill)
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 @@ ill_lookup_on_ifindex(uint_t index, boolean_t isv6, queue_t *q, mblk_t *mp,
}
/*
+ * 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 @@ ip_sioctl_addr_tail(ipif_t *ipif, sin_t *sin, queue_t *q, mblk_t *mp,
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 @@ ip_sioctl_addr_tail(ipif_t *ipif, sin_t *sin, queue_t *q, mblk_t *mp,
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 @@ ip_sioctl_addr_tail(ipif_t *ipif, sin_t *sin, queue_t *q, mblk_t *mp,
}
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 @@ ill_dl_down(ill_t *ill)
* 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_dl_down(ill_t *ill)
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 @@ ipif_up_done(ipif_t *ipif)
rw_enter(&ill_g_lock, RW_READER);
mutex_enter(&ip_addr_avail_lock);
/* Mark it up, and increment counters. */
- ill->ill_ipif_up_count++;
ipif->ipif_flags |= IPIF_UP;
+ ill->ill_ipif_up_count++;
err = ip_addr_availability_check(ipif);
mutex_exit(&ip_addr_avail_lock);
rw_exit(&ill_g_lock);
@@ -22110,6 +22336,57 @@ ill_phyint_reinit(ill_t *ill)
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 @@ ill_is_probeonly(ill_t *ill)
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);
+}
diff --git a/usr/src/uts/common/inet/ip/ip_multi.c b/usr/src/uts/common/inet/ip/ip_multi.c
index f6fe60db0d..ae2d6e8abd 100644
--- a/usr/src/uts/common/inet/ip/ip_multi.c
+++ b/usr/src/uts/common/inet/ip/ip_multi.c
@@ -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 @@ ip_multicast_loopback(queue_t *q, ill_t *ill, mblk_t *mp_orig, int fanout_flags,
{
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 @@ ip_multicast_loopback(queue_t *q, ill_t *ill, mblk_t *mp_orig, int fanout_flags,
} 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 = {
diff --git a/usr/src/uts/common/inet/ip/ip_ndp.c b/usr/src/uts/common/inet/ip/ip_ndp.c
index de75be651d..0eccc9d360 100644
--- a/usr/src/uts/common/inet/ip/ip_ndp.c
+++ b/usr/src/uts/common/inet/ip/ip_ndp.c
@@ -526,9 +526,8 @@ ndp_inactive(nce_t *nce)
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 @@ ndp_inactive(nce_t *nce)
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 @@ ndp_process(nce_t *nce, uchar_t *hw_addr, uint32_t flag, boolean_t is_adv)
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 @@ ndp_process(nce_t *nce, uchar_t *hw_addr, uint32_t flag, boolean_t is_adv)
* 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
diff --git a/usr/src/uts/common/inet/ip/ip_netinfo.c b/usr/src/uts/common/inet/ip/ip_netinfo.c
new file mode 100644
index 0000000000..bad11757c5
--- /dev/null
+++ b/usr/src/uts/common/inet/ip/ip_netinfo.c
@@ -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));
+}
diff --git a/usr/src/uts/common/inet/ip6.h b/usr/src/uts/common/inet/ip6.h
index eb80877b21..966983bb20 100644
--- a/usr/src/uts/common/inet/ip6.h
+++ b/usr/src/uts/common/inet/ip6.h
@@ -366,6 +366,7 @@ extern int ip_hdr_complete_v6(ip6_t *, zoneid_t);
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_wput_md_v6(queue_t *, mblk_t *, conn_t *);
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 *);
diff --git a/usr/src/uts/common/inet/ip_if.h b/usr/src/uts/common/inet/ip_if.h
index 96841cca5d..e32ba29a8e 100644
--- a/usr/src/uts/common/inet/ip_if.h
+++ b/usr/src/uts/common/inet/ip_if.h
@@ -164,6 +164,9 @@ extern ill_t *ill_lookup_on_ifindex(uint_t, boolean_t, queue_t *, mblk_t *,
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 int ill_up_ipifs(ill_t *, queue_t *, mblk_t *);
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 *);
diff --git a/usr/src/uts/common/inet/ip_impl.h b/usr/src/uts/common/inet/ip_impl.h
index f86839d5b9..57be18aed4 100644
--- a/usr/src/uts/common/inet/ip_impl.h
+++ b/usr/src/uts/common/inet/ip_impl.h
@@ -41,6 +41,8 @@ extern "C" {
#ifdef _KERNEL
+#include <sys/sdt.h>
+
#define IP_MOD_ID 5701
#ifdef _BIG_ENDIAN
@@ -480,13 +482,20 @@ typedef struct ip_pdescinfo_s PDESCINFO_STRUCT(2) ip_pdescinfo_t;
* 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;
diff --git a/usr/src/uts/common/inet/ip_ire.h b/usr/src/uts/common/inet/ip_ire.h
index b52b9492f4..b32847944e 100644
--- a/usr/src/uts/common/inet/ip_ire.h
+++ b/usr/src/uts/common/inet/ip_ire.h
@@ -380,9 +380,6 @@ extern void ire_fastpath_list_dispatch(ill_t *,
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 *);
diff --git a/usr/src/uts/common/inet/ip_netinfo.h b/usr/src/uts/common/inet/ip_netinfo.h
new file mode 100644
index 0000000000..8523f8afea
--- /dev/null
+++ b/usr/src/uts/common/inet/ip_netinfo.h
@@ -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 */
diff --git a/usr/src/uts/common/inet/ipf/fil.c b/usr/src/uts/common/inet/ipf/fil.c
index 1dd95e9ba5..40443d5ab5 100644
--- a/usr/src/uts/common/inet/ipf/fil.c
+++ b/usr/src/uts/common/inet/ipf/fil.c
@@ -184,6 +184,9 @@ u_long fr_frouteok[2] = {0, 0};
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 INLINE int fr_updateipid __P((fr_info_t *));
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 @@ int out;
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 @@ u_32_t *msk;
/* ------------------------------------------------------------------------ */
+/* 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 @@ u_32_t *msk;
/* 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)
-frentry_t *fr;
+static void frsynclist(action, v, ifp, ifname, fr)
+int action, v;
void *ifp;
+char *ifname;
+frentry_t *fr;
{
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 @@ void *ifp;
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 @@ void *ifp;
/* ------------------------------------------------------------------------ */
/* 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 @@ caddr_t data;
/*
* 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 @@ fr_info_t *fin;
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 @@ fr_info_t *fin;
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 @@ fr_info_t *fin;
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 @@ ipftuneable_t ipf_tuneables[] = {
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 @@ void fr_resolvedest(fdp, v)
frdest_t *fdp;
int v;
{
- void *ifp;
-
- ifp = NULL;
- v = v; /* LINT */
+ fdp->fd_ifp = NULL;
- if (*fdp->fd_ifname != '\0') {
- ifp = GETIFP(fdp->fd_ifname, v);
- if (ifp == NULL)
- ifp = (void *)-1;
+ 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 */
diff --git a/usr/src/uts/common/inet/ipf/ip_auth.c b/usr/src/uts/common/inet/ipf/ip_auth.c
index b6f0844354..bf2afb2ba4 100644
--- a/usr/src/uts/common/inet/ipf/ip_auth.c
+++ b/usr/src/uts/common/inet/ipf/ip_auth.c
@@ -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 @@ struct file;
# 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 @@ frauthent_t *fae_list = NULL;
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 @@ fr_info_t *fin;
#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 @@ int mode;
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 @@ fr_authioctlloop:
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 @@ fr_authioctlloop:
# 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
diff --git a/usr/src/uts/common/inet/ipf/ip_fil_solaris.c b/usr/src/uts/common/inet/ipf/ip_fil_solaris.c
index 851ae007f9..5380f0f773 100644
--- a/usr/src/uts/common/inet/ipf/ip_fil_solaris.c
+++ b/usr/src/uts/common/inet/ipf/ip_fil_solaris.c
@@ -60,6 +60,7 @@ static const char rcsid[] = "@(#)$Id: ip_fil_solaris.c,v 2.62.2.19 2005/07/13 21
#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 @@ timeout_id_t fr_timer_id;
#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_mtudisc = NULL;
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 @@ int ipldetach()
}
#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 @@ int ipldetach()
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 @@ int iplattach __P((void))
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 @@ int iplattach __P((void))
#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 @@ int *rp;
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 @@ int *rp;
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 @@ int *rp;
}
-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;
-
- 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;
+ 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);
+
+ return (phy);
}
-
/*
* routines below for saving IP headers to buffer
*/
@@ -675,7 +952,6 @@ mblk_t *m, **mpp;
{
qpktinfo_t qpi, *qpip;
fr_info_t fnew;
- qif_t *qif;
ip_t *ip;
int i, hlen;
@@ -698,8 +974,8 @@ mblk_t *m, **mpp;
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 @@ mblk_t *m, **mpp;
}
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 @@ int dst;
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 @@ int dst;
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 dst;
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 @@ int dst;
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 @@ int dst;
return fr_send_ip(fin, m, &m);
}
-#ifdef IRE_ILL_CN
#include <sys/time.h>
#include <sys/varargs.h>
@@ -940,120 +1207,68 @@ static void rate_limit_message(int rate, const char *message, ...)
#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;
+
+ 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;
+ }
-#ifdef USE_INET6
-#ifdef IRE_ILL_CN
- s_ill_t *ill;
-#endif
-#endif
- if ((qifptr == NULL) || (qifptr == (void *)-1))
+ 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);
- break;
case FRI_PEERADDR :
- sin.sin_addr.s_addr = QF_V4_PEERADDR(qif);
+ type[0] = NA_PEER;
break;
+
+ 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);
-#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);
+ type[1] = NA_NETMASK;
+
+ 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 @@ fr_info_t *fin;
#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,63 +1402,190 @@ void fr_slowtimer __P((void *ptr))
}
+/* ------------------------------------------------------------------------ */
+/* Function: fr_pullup */
+/* Returns: NULL == pullup failed, else pointer to protocol header */
+/* Parameters: m(I) - pointer to buffer where data packet starts */
+/* fin(I) - pointer to packet information */
+/* len(I) - number of bytes to pullup */
+/* */
+/* Attempt to move at least len bytes (from the start of the buffer) into a */
+/* single buffer for ease of access. Operating system native functions are */
+/* used to manage buffers - if necessary. If the entire packet ends up in */
+/* a single buffer, set the FI_COALESCE flag even though fr_coalesce() has */
+/* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */
+/* and ONLY if the pullup succeeds. */
+/* */
+/* We assume that 'min' is a pointer to a buffer that is part of the chain */
+/* of buffers that starts at *fin->fin_mp. */
+/* ------------------------------------------------------------------------ */
+void *fr_pullup(min, fin, len)
+mb_t *min;
+fr_info_t *fin;
+int len;
+{
+ qpktinfo_t *qpi = fin->fin_qpi;
+ int out = fin->fin_out, dpoff, ipoff;
+ mb_t *m = min, *m1, *m2;
+ char *ip;
+
+ if (m == NULL)
+ return NULL;
+
+ ip = (char *)fin->fin_ip;
+ if ((fin->fin_flx & FI_COALESCE) != 0)
+ return ip;
+
+ ipoff = fin->fin_ipoff;
+ if (fin->fin_dp != NULL)
+ dpoff = (char *)fin->fin_dp - (char *)ip;
+ else
+ dpoff = 0;
+
+ if (M_LEN(m) < len) {
+
+ /*
+ * pfil_precheck ensures the IP header is on a 32bit
+ * aligned address so simply fail if that isn't currently
+ * the case (should never happen).
+ */
+ int inc = 0;
+
+ if (ipoff > 0) {
+ if ((ipoff & 3) != 0) {
+ inc = 4 - (ipoff & 3);
+ if (m->b_rptr - inc >= m->b_datap->db_base)
+ m->b_rptr -= inc;
+ else
+ 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);
+ *fin->fin_mp = NULL;
+ fin->fin_m = NULL;
+ fin->fin_ip = NULL;
+ fin->fin_dp = NULL;
+ qpi->qpi_data = NULL;
+ return NULL;
+ }
+ m->b_prev = m2;
+ m->b_rptr += inc;
+ fin->fin_m = m;
+ ip = MTOD(m, char *) + ipoff;
+ qpi->qpi_data = ip;
+ }
+
+ ATOMIC_INCL(frstats[out].fr_pull[0]);
+ fin->fin_ip = (ip_t *)ip;
+ if (fin->fin_dp != NULL)
+ fin->fin_dp = (char *)fin->fin_ip + dpoff;
+
+ if (len == fin->fin_plen)
+ fin->fin_flx |= FI_COALESCE;
+ return ip;
+}
+
+
/*
- * Function: fr_fastroute
- * Returns: 0: success;
- * -1: failed
+ * 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.
+ * 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
+ * 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
+ * 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;
+ net_data_t net_data_p;
+ net_inject_t inj_data;
mblk_t *mp = NULL;
+ frentry_t *fr = fin->fin_fr;
qpktinfo_t *qpi;
- frentry_t *fr;
- qif_t *qif;
ip_t *ip;
+
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ struct sockaddr *sinp;
#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;
+
+ 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;
@@ -1287,14 +1593,16 @@ frdest_t *fdp;
* 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
+ *
+ * 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)
+
+ 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;
+ } 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;
}
@@ -1307,326 +1615,297 @@ frdest_t *fdp;
*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;
- }
+ 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 ((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 (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) {
- 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;
+ sin->sin_addr = fdp->fd_ip;
+ } else {
+ sin6->sin6_addr = fdp->fd_ip6.in6;
}
-#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;
+ } else {
+ if (fin->fin_v == 4) {
+ sin->sin_addr = ip->ip_dst;
+ } else {
+ sin6->sin6_addr = ((ip6_t *)ip)->ip6_dst;
}
-#endif
- else
- goto bad_fastroute;
+ inj_data.ni_physical = net_routeto(net_data_p, sinp);
}
-#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
+ /* disable hardware checksum */
+ DB_CKSUMFLAGS(mb) = 0;
- 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;
+ *mpp = mb;
- 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 */
+ if (fin->fin_out == 0) {
+ void *saveifp;
+ u_32_t pass;
-#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;
+ 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;
}
-#ifndef sparc
- if (fin->fin_v == 4) {
- __iplen = (u_short)ip->ip_len,
- __ipoff = (u_short)ip->ip_off;
+ fin->fin_out = 0;
+ fin->fin_ifp = saveifp;
- 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;
+ 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;
- 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);
+ ip->ip_len = htons(__iplen);
+ ip->ip_off = htons(__ipoff);
+ }
#endif
- READ_ENTER(&ipf_global);
- return 0;
+
+ if (net_data_p) {
+ if (net_inject(net_data_p, NI_DIRECT_OUT, &inj_data) < 0) {
+ return (-1);
}
-#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 */
}
+
+ fr_frouteok[0]++;
+ return 0;
bad_fastroute:
-#ifndef IRE_ILL_CN
-#if SOLARIS2 >= 8
- if (dir != NULL)
- ire_refrele(dir);
-#endif
-#endif
freemsg(mb);
- ATOMIC_INCL(fr_frouteok[1]);
+ fr_frouteok[1]++;
return -1;
}
/* ------------------------------------------------------------------------ */
-/* Function: fr_pullup */
-/* Returns: NULL == pullup failed, else pointer to protocol header */
-/* Parameters: m(I) - pointer to buffer where data packet starts */
-/* fin(I) - pointer to packet information */
-/* len(I) - number of bytes to pullup */
+/* 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 */
/* */
-/* Attempt to move at least len bytes (from the start of the buffer) into a */
-/* single buffer for ease of access. Operating system native functions are */
-/* used to manage buffers - if necessary. If the entire packet ends up in */
-/* a single buffer, set the FI_COALESCE flag even though fr_coalesce() has */
-/* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */
-/* and ONLY if the pullup succeeds. */
+/* 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 */
/* */
-/* We assume that 'min' is a pointer to a buffer that is part of the chain */
-/* of buffers that starts at *fin->fin_mp. */
+/* Calling ipf_hook. */
/* ------------------------------------------------------------------------ */
-void *fr_pullup(min, fin, len)
-mb_t *min;
-fr_info_t *fin;
-int len;
+/*ARGSUSED*/
+int ipf_hook_in(hook_event_token_t token, hook_data_t info)
{
- qpktinfo_t *qpi = fin->fin_qpi;
- int out = fin->fin_out, dpoff, ipoff;
- mb_t *m = min;
- char *ip;
+ return ipf_hook(info, 0, 0);
+}
- if (m == NULL)
- return NULL;
- ip = (char *)fin->fin_ip;
- if ((fin->fin_flx & FI_COALESCE) != 0)
- return ip;
+/* ------------------------------------------------------------------------ */
+/* 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);
+}
- ipoff = fin->fin_ipoff;
- if (fin->fin_dp != NULL)
- dpoff = (char *)fin->fin_dp - (char *)ip;
+/* ------------------------------------------------------------------------ */
+/* 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
- dpoff = 0;
+ 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;
- if (M_LEN(m) < len) {
+}
- /*
- * pfil_precheck ensures the IP header is on a 32bit
- * aligned address so simply fail if that isn't currently
- * the case (should never happen).
- */
- int inc = 0;
- if (ipoff > 0) {
- if ((ipoff & 3) != 0) {
- inc = 4 - (ipoff & 3);
- if (m->b_rptr - inc >= m->b_datap->db_base)
- m->b_rptr -= inc;
- else
- inc = 0;
- }
- }
- if (pullupmsg(m, len + ipoff + inc) == 0) {
- ATOMIC_INCL(frstats[out].fr_pull[1]);
- FREE_MB_T(*fin->fin_mp);
- *fin->fin_mp = NULL;
- fin->fin_m = NULL;
- fin->fin_ip = NULL;
- fin->fin_dp = NULL;
- qpi->qpi_data = NULL;
- return NULL;
- }
- m->b_rptr += inc;
- fin->fin_m = m;
- ip = MTOD(m, char *) + ipoff;
- qpi->qpi_data = ip;
+/* ------------------------------------------------------------------------ */
+/* 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;
}
- ATOMIC_INCL(frstats[out].fr_pull[0]);
- fin->fin_ip = (ip_t *)ip;
- if (fin->fin_dp != NULL)
- fin->fin_dp = (char *)fin->fin_ip + dpoff;
+ return 0;
+}
- if (len == fin->fin_plen)
- fin->fin_flx |= FI_COALESCE;
- return ip;
+
+/* ------------------------------------------------------------------------ */
+/* 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;
}
diff --git a/usr/src/uts/common/inet/ipf/ip_log.c b/usr/src/uts/common/inet/ipf/ip_log.c
index 364b2e08e5..380bf597ba 100644
--- a/usr/src/uts/common/inet/ipf/ip_log.c
+++ b/usr/src/uts/common/inet/ipf/ip_log.c
@@ -254,15 +254,16 @@ u_int flags;
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 @@ u_int flags;
* 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;
- (void) strncpy(ipfl.fl_ifname, IFNAME(ifp), sizeof(ipfl.fl_ifname));
+ 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(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \
- (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
- (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
- COPYIFNAME(ifp, ipfl.fl_ifname);
+# 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))
+ COPYIFNAME(ifp, ipfl.fl_ifname);
+# 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 @@ struct uio *uio;
*/
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);
diff --git a/usr/src/uts/common/inet/ipf/ip_nat.c b/usr/src/uts/common/inet/ipf/ip_nat.c
index ceaa980158..a4e2cecf31 100644
--- a/usr/src/uts/common/inet/ipf/ip_nat.c
+++ b/usr/src/uts/common/inet/ipf/ip_nat.c
@@ -171,9 +171,6 @@ u_long fr_defnatage = DEF_NAT_AGE,
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 @@ static INLINE int nat_finalise __P((fr_info_t *, nat_t *, natinfo_t *,
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 @@ struct hostmap *hm;
/* ------------------------------------------------------------------------ */
/* 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 @@ u_32_t n;
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 @@ u_32_t n;
/* ------------------------------------------------------------------------ */
/* 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 @@ u_32_t n;
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 @@ int getlock;
}
n = NULL;
nat_stats.ns_rules++;
-#if SOLARIS
- pfil_delayed_copy = 0;
-#endif
if (getlock) {
RWLOCK_EXIT(&ipf_nat); /* WRITE */
}
@@ -1067,10 +1043,6 @@ int getlock;
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 @@ int logtype;
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 @@ static int nat_clearlist()
}
i++;
}
-#if SOLARIS
- pfil_delayed_copy = 1;
-#endif
nat_masks = 0;
rdr_masks = 0;
return i;
@@ -2147,9 +2112,6 @@ int direction;
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 @@ int direction;
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 @@ int direction;
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 @@ int dir;
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 @@ u_32_t nflags;
{
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 @@ u_32_t nflags;
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 @@ u_32_t nflags;
* 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 @@ u_32_t nflags;
* 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);
- else
- fix_incksum(fin, &fin->fin_ip->ip_sum,
+ fix_outcksum(&fin->fin_ip->ip_sum,
nat->nat_ipsumd);
+ else
+ fix_incksum(&fin->fin_ip->ip_sum,
+ nat->nat_ipsumd);
}
#endif
}
@@ -3750,11 +3720,17 @@ u_32_t nflags;
/*
* 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 @@ int natadd;
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 @@ u_32_t nflags;
#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 @@ u_32_t nflags;
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 @@ u_int nflags;
* 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 @@ void fr_natexpire()
/* ------------------------------------------------------------------------ */
-/* 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 @@ void *ifp;
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 @@ void *ifp;
* new one.
*/
sum1 = nat->nat_outip.s_addr;
- if (fr_ifpaddr(4, FRI_NORMAL, ifp2, &in, NULL) != -1)
- nat->nat_outip = in;
+ nat->nat_outip = *addr;
sum2 = nat->nat_outip.s_addr;
- if (sum1 == sum2)
- continue;
+ } 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;
+
/*
- * 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.
+ * Change the map-to address to be the same as the
+ * new one.
*/
- sumd += nat->nat_sumd[0];
- nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16);
- nat->nat_sumd[1] = nat->nat_sumd[0];
+ 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;
+ } 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 @@ int dir;
/* 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 @@ u_short *csump;
cp[2] = maxmss / 256;
cp[3] = maxmss & 0xff;
CALC_SUMD(mss, maxmss, sumd);
- fix_outcksum(fin, csump, sumd);
+ fix_outcksum(csump, sumd);
}
break;
default:
diff --git a/usr/src/uts/common/inet/ipf/ip_proxy.c b/usr/src/uts/common/inet/ipf/ip_proxy.c
index 99f8a14b88..d48e83ff74 100644
--- a/usr/src/uts/common/inet/ipf/ip_proxy.c
+++ b/usr/src/uts/common/inet/ipf/ip_proxy.c
@@ -462,10 +462,8 @@ int appr_check(fin, nat)
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 @@ nat_t *nat;
#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 @@ nat_t *nat;
* 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 @@ nat_t *nat;
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 @@ nat_t *nat;
#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
diff --git a/usr/src/uts/common/inet/ipf/ip_state.c b/usr/src/uts/common/inet/ipf/ip_state.c
index ec63d80736..83cd7ebbc8 100644
--- a/usr/src/uts/common/inet/ipf/ip_state.c
+++ b/usr/src/uts/common/inet/ipf/ip_state.c
@@ -1092,15 +1092,15 @@ u_int flags;
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 @@ u_int flags;
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 @@ u_32_t cmask;
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 @@ ipstate_t *is;
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 @@ ipstate_t *is;
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 @@ ipstate_t *is;
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 @@ ipstate_t *is;
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 @@ ipstate_t *is;
/* ------------------------------------------------------------------------ */
/* 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 @@ ipstate_t *is;
/* 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 @@ void *ifp;
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);
}
diff --git a/usr/src/uts/common/inet/pfil/misc.c b/usr/src/uts/common/inet/ipf/misc.c
index 2a8c84dd4c..a49a0ca5c5 100644
--- a/usr/src/uts/common/inet/pfil/misc.c
+++ b/usr/src/uts/common/inet/ipf/misc.c
@@ -3,17 +3,22 @@
*
* 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 "compat.h"
+#include <sys/ddi.h>
#ifdef __hpux
# define BCOPY(a,b,c) bcopy((caddr_t)a, (caddr_t)b, c)
@@ -32,11 +37,11 @@ char *buf;
mblk_t *m;
for (m = min; (m != NULL) && (len > 0); m = m->b_cont) {
- if (MTYPE(m) != M_DATA)
+ if (m->b_datap->db_type != M_DATA)
continue;
s = m->b_rptr;
mlen = m->b_wptr - s;
- olen = MIN(off, mlen);
+ olen = min(off, mlen);
if ((olen == mlen) || (olen < off)) {
off -= olen;
continue;
@@ -45,7 +50,7 @@ char *buf;
s += olen;
mlen -= olen;
}
- clen = MIN(mlen, len);
+ clen = min(mlen, len);
BCOPY(s, bp, clen);
len -= clen;
bp += clen;
@@ -64,12 +69,12 @@ char *buf;
for (m = min, mp = NULL; (m != NULL) && (len > 0); m = m->b_cont) {
mp = m;
- if (MTYPE(m) != M_DATA)
+ if (m->b_datap->db_type != M_DATA)
continue;
s = m->b_rptr;
mlen = m->b_wptr - s;
- olen = MIN(off, mlen);
+ olen = min(off, mlen);
if ((olen == mlen) || (olen < off)) {
off -= olen;
continue;
@@ -78,7 +83,7 @@ char *buf;
s += olen;
mlen -= olen;
}
- clen = MIN(mlen, len);
+ clen = min(mlen, len);
BCOPY(bp, s, clen);
len -= clen;
bp += clen;
@@ -90,7 +95,7 @@ char *buf;
if (mlen > 0) {
if (mlen > len)
mlen = len;
- bcopy((char *)bp, (char *)mp->b_wptr, mlen);
+ BCOPY(bp, mp->b_wptr, mlen);
bp += mlen;
len -= mlen;
mp->b_wptr += mlen;
@@ -106,7 +111,7 @@ char *buf;
if (len > 0) {
m = allocb(len, BPRI_MED);
if (m != NULL) {
- bcopy((char *)bp, (char *)m->b_wptr, len);
+ BCOPY(bp, m->b_wptr, len);
m->b_band = mp->b_band;
m->b_wptr += len;
linkb(mp, m);
diff --git a/usr/src/uts/common/inet/ipf/netinet/ip_compat.h b/usr/src/uts/common/inet/ipf/netinet/ip_compat.h
index bf6b8f67b0..365e3b010e 100644
--- a/usr/src/uts/common/inet/ipf/netinet/ip_compat.h
+++ b/usr/src/uts/common/inet/ipf/netinet/ip_compat.h
@@ -202,6 +202,28 @@ struct ip6_ext {
};
# 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 @@ typedef unsigned int u_32_t;
# 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 @@ typedef unsigned int u_32_t;
# 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 @@ extern struct s_ill_s *s_ill_g_head; /* ILL List Head */
# 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 @@ typedef struct iplog_select_s {
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 @@ extern void *get_unit __P((char *, int));
# 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 @@ typedef struct mbuf mb_t;
# 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 @@ typedef struct mbuf mb_t;
# 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_read_enter __P((eMrwlock_t *, char *, int));
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 @@ MALLOC_DECLARE(M_IPFILTER);
#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
diff --git a/usr/src/uts/common/inet/ipf/netinet/ip_fil.h b/usr/src/uts/common/inet/ipf/netinet/ip_fil.h
index e7ec154f4f..7fc1712dd0 100644
--- a/usr/src/uts/common/inet/ipf/netinet/ip_fil.h
+++ b/usr/src/uts/common/inet/ipf/netinet/ip_fil.h
@@ -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 @@ typedef struct ipftune {
/*
+ * 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_addipftune __P((ipftuneable_t *));
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));
diff --git a/usr/src/uts/common/inet/ipf/netinet/ip_irc_pxy.c b/usr/src/uts/common/inet/ipf/netinet/ip_irc_pxy.c
index 4b7a139048..a0b784053a 100644
--- a/usr/src/uts/common/inet/ipf/netinet/ip_irc_pxy.c
+++ b/usr/src/uts/common/inet/ipf/netinet/ip_irc_pxy.c
@@ -369,7 +369,7 @@ nat_t *nat;
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;
}
diff --git a/usr/src/uts/common/inet/ipf/netinet/ip_nat.h b/usr/src/uts/common/inet/ipf/netinet/ip_nat.h
index 930e8aa103..9b47591591 100644
--- a/usr/src/uts/common/inet/ipf/netinet/ip_nat.h
+++ b/usr/src/uts/common/inet/ipf/netinet/ip_nat.h
@@ -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 ipf_hostmap_sz;
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 int fr_natin __P((fr_info_t *, nat_t *, int, u_32_t));
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 *));
diff --git a/usr/src/uts/common/inet/ipf/netinet/ip_state.h b/usr/src/uts/common/inet/ipf/netinet/ip_state.h
index 7b5891d86d..5f35878d89 100644
--- a/usr/src/uts/common/inet/ipf/netinet/ip_state.h
+++ b/usr/src/uts/common/inet/ipf/netinet/ip_state.h
@@ -248,7 +248,7 @@ extern int fr_stateinit __P((void));
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));
diff --git a/usr/src/uts/common/inet/ipf/solaris.c b/usr/src/uts/common/inet/ipf/solaris.c
index 0c21d1f15f..9fe1660077 100644
--- a/usr/src/uts/common/inet/ipf/solaris.c
+++ b/usr/src/uts/common/inet/ipf/solaris.c
@@ -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 @@ static int ipf_identify __P((dev_info_t *));
#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 @@ static const filter_kstats_t ipf_kstat_tmp = {
{ "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 _init()
int ipfinst;
ipf_kstat_init();
+
ipfinst = mod_install(&modlink1);
+
if (ipfinst != 0)
ipf_kstat_fini();
#ifdef IPFDEBUG
@@ -332,6 +336,7 @@ int _fini(void)
#endif
if (ipfinst == 0)
ipf_kstat_fini();
+
return ipfinst;
}
@@ -375,12 +380,6 @@ ddi_attach_cmd_t cmd;
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 @@ ddi_attach_cmd_t cmd;
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 @@ ddi_detach_cmd_t cmd;
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 @@ ddi_detach_cmd_t cmd;
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 @@ void *arg, **result;
/*
- * 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.
*/
diff --git a/usr/src/uts/common/inet/pfil/compat.h b/usr/src/uts/common/inet/pfil/compat.h
deleted file mode 100644
index ddaa3354e2..0000000000
--- a/usr/src/uts/common/inet/pfil/compat.h
+++ /dev/null
@@ -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
diff --git a/usr/src/uts/common/inet/pfil/ndd.c b/usr/src/uts/common/inet/pfil/ndd.c
deleted file mode 100644
index ce85cc0091..0000000000
--- a/usr/src/uts/common/inet/pfil/ndd.c
+++ /dev/null
@@ -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;
-}
diff --git a/usr/src/uts/common/inet/pfil/os.h b/usr/src/uts/common/inet/pfil/os.h
deleted file mode 100644
index b7a77e130e..0000000000
--- a/usr/src/uts/common/inet/pfil/os.h
+++ /dev/null
@@ -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
diff --git a/usr/src/uts/common/inet/pfil/pfil.c b/usr/src/uts/common/inet/pfil/pfil.c
deleted file mode 100644
index d44f1ac5bc..0000000000
--- a/usr/src/uts/common/inet/pfil/pfil.c
+++ /dev/null
@@ -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;
-}
diff --git a/usr/src/uts/common/inet/pfil/pfil.h b/usr/src/uts/common/inet/pfil/pfil.h
deleted file mode 100644
index 97f926da8b..0000000000
--- a/usr/src/uts/common/inet/pfil/pfil.h
+++ /dev/null
@@ -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_ */
diff --git a/usr/src/uts/common/inet/pfil/pfild.h b/usr/src/uts/common/inet/pfil/pfild.h
deleted file mode 100644
index e866e514ae..0000000000
--- a/usr/src/uts/common/inet/pfil/pfild.h
+++ /dev/null
@@ -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;
-};
diff --git a/usr/src/uts/common/inet/pfil/pfildrv.c b/usr/src/uts/common/inet/pfil/pfildrv.c
deleted file mode 100644
index 45d694d304..0000000000
--- a/usr/src/uts/common/inet/pfil/pfildrv.c
+++ /dev/null
@@ -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
diff --git a/usr/src/uts/common/inet/pfil/pfilstream.c b/usr/src/uts/common/inet/pfil/pfilstream.c
deleted file mode 100644
index 51d1b30d5a..0000000000
--- a/usr/src/uts/common/inet/pfil/pfilstream.c
+++ /dev/null
@@ -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);
-}
diff --git a/usr/src/uts/common/inet/pfil/pkt.c b/usr/src/uts/common/inet/pfil/pkt.c
deleted file mode 100644
index 5c0bd72ddc..0000000000
--- a/usr/src/uts/common/inet/pfil/pkt.c
+++ /dev/null
@@ -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 */
diff --git a/usr/src/uts/common/inet/pfil/qif.c b/usr/src/uts/common/inet/pfil/qif.c
deleted file mode 100644
index ec1ec676f2..0000000000
--- a/usr/src/uts/common/inet/pfil/qif.c
+++ /dev/null
@@ -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);
-}
diff --git a/usr/src/uts/common/inet/pfil/qif.h b/usr/src/uts/common/inet/pfil/qif.h
deleted file mode 100644
index 7371ab420a..0000000000
--- a/usr/src/uts/common/inet/pfil/qif.h
+++ /dev/null
@@ -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;
diff --git a/usr/src/uts/common/inet/tcp.h b/usr/src/uts/common/inet/tcp.h
index cede68250d..54d46f7f1b 100644
--- a/usr/src/uts/common/inet/tcp.h
+++ b/usr/src/uts/common/inet/tcp.h
@@ -568,6 +568,9 @@ extern void *tcp_get_conn(void *arg);
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
diff --git a/usr/src/uts/common/inet/tcp/tcp.c b/usr/src/uts/common/inet/tcp/tcp.c
index d5890ec810..2361fcaacc 100644
--- a/usr/src/uts/common/inet/tcp/tcp.c
+++ b/usr/src/uts/common/inet/tcp/tcp.c
@@ -45,6 +45,7 @@ const char tcp_version[] = "%Z%%M% %I% %E% SMI";
#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 @@ const char tcp_version[] = "%Z%%M% %I% %E% SMI";
#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 @@ const char tcp_version[] = "%Z%%M% %I% %E% SMI";
* 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 @@ static void tcp_fill_header(tcp_t *tcp, uchar_t *rptr, clock_t now,
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 @@ tcp_send_data(tcp_t *tcp, queue_t *q, mblk_t *mp)
* 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);
+ 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 @@ tcp_multisend(queue_t *q, tcp_t *tcp, const int mss, const int tcp_hdr_len,
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 @@ tcp_multisend(queue_t *q, tcp_t *tcp, const int mss, const int tcp_hdr_len,
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 @@ legacy_send_no_md:
}
}
+ 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 @@ legacy_send_no_md:
*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 @@ tcp_xmit_listeners_reset(mblk_t *mp, uint_t ip_hdr_len, zoneid_t zoneid)
* 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)
diff --git a/usr/src/uts/common/inet/tcp/tcp_fusion.c b/usr/src/uts/common/inet/tcp/tcp_fusion.c
index a6c1fe1ea1..7cca7bda15 100644
--- a/usr/src/uts/common/inet/tcp/tcp_fusion.c
+++ b/usr/src/uts/common/inet/tcp/tcp_fusion.c
@@ -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 @@ tcp_fuse_output(tcp_t *tcp, mblk_t *mp, uint32_t send_size)
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 @@ tcp_fuse_output(tcp_t *tcp, mblk_t *mp, uint32_t send_size)
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_output(tcp_t *tcp, mblk_t *mp, uint32_t send_size)
*/
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 @@ tcp_fuse_output(tcp_t *tcp, mblk_t *mp, uint32_t send_size)
* 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 @@ tcp_fuse_output(tcp_t *tcp, mblk_t *mp, uint32_t send_size)
/* 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 @@ tcp_fuse_output(tcp_t *tcp, mblk_t *mp, uint32_t send_size)
}
}
return (B_TRUE);
+unfuse:
+ tcp_unfuse(tcp);
+ return (B_FALSE);
}
/*
diff --git a/usr/src/uts/common/inet/udp/udp.c b/usr/src/uts/common/inet/udp/udp.c
index 95f2d9b64b..ae99e06f72 100644
--- a/usr/src/uts/common/inet/udp/udp.c
+++ b/usr/src/uts/common/inet/udp/udp.c
@@ -53,6 +53,7 @@ const char udp_version[] = "%Z%%M% %I% %E% SMI";
#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 @@ udp_send_data(udp_t *udp, queue_t *q, mblk_t *mp, ipha_t *ipha)
* 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)
diff --git a/usr/src/uts/common/io/bge/bge_send.c b/usr/src/uts/common/io/bge/bge_send.c
index d886d19636..0a29b29510 100644
--- a/usr/src/uts/common/io/bge/bge_send.c
+++ b/usr/src/uts/common/io/bge/bge_send.c
@@ -409,23 +409,12 @@ bge_send(bge_t *bgep, mblk_t *mp)
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;
diff --git a/usr/src/uts/common/io/hook.c b/usr/src/uts/common/io/hook.c
new file mode 100644
index 0000000000..7e791647e4
--- /dev/null
+++ b/usr/src/uts/common/io/hook.c
@@ -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));
+}
diff --git a/usr/src/uts/common/io/neti.c b/usr/src/uts/common/io/neti.c
new file mode 100644
index 0000000000..3f7ae3c611
--- /dev/null
+++ b/usr/src/uts/common/io/neti.c
@@ -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));
+}
diff --git a/usr/src/uts/common/io/stream.c b/usr/src/uts/common/io/stream.c
index 4f7e330b39..ec18ed82e3 100644
--- a/usr/src/uts/common/io/stream.c
+++ b/usr/src/uts/common/io/stream.c
@@ -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 @@ pullupmsg(mblk_t *mp, ssize_t len)
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 @@ pullupmsg(mblk_t *mp, ssize_t len)
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 @@ msgpullup(mblk_t *mp, ssize_t len)
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 @@ msgpullup(mblk_t *mp, ssize_t len)
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 */
diff --git a/usr/src/uts/common/sys/Makefile b/usr/src/uts/common/sys/Makefile
index e133c8a49e..4239f7bf6f 100644
--- a/usr/src/uts/common/sys/Makefile
+++ b/usr/src/uts/common/sys/Makefile
@@ -246,6 +246,9 @@ CHKHDRS= \
gld.h \
gldpriv.h \
hdio.h \
+ hook.h \
+ hook_event.h \
+ hook_impl.h \
hwconf.h \
ia.h \
iapriocntl.h \
@@ -339,6 +342,7 @@ CHKHDRS= \
ndifm.h \
ndi_impldefs.h \
netconfig.h \
+ neti.h \
nexusdefs.h \
note.h \
nvpair.h \
@@ -353,6 +357,7 @@ CHKHDRS= \
pathconf.h \
pathname.h \
pattr.h \
+ queue.h \
serializer.h \
pbio.h \
pccard.h \
diff --git a/usr/src/uts/common/sys/condvar_impl.h b/usr/src/uts/common/sys/condvar_impl.h
index f94a6cb54e..15adcedb93 100644
--- a/usr/src/uts/common/sys/condvar_impl.h
+++ b/usr/src/uts/common/sys/condvar_impl.h
@@ -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 @@ typedef struct _condvar_impl {
#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
diff --git a/usr/src/uts/common/sys/hook.h b/usr/src/uts/common/sys/hook.h
new file mode 100644
index 0000000000..c7a6779dc5
--- /dev/null
+++ b/usr/src/uts/common/sys/hook.h
@@ -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 */
diff --git a/usr/src/uts/common/sys/hook_event.h b/usr/src/uts/common/sys/hook_event.h
new file mode 100644
index 0000000000..7ad1214223
--- /dev/null
+++ b/usr/src/uts/common/sys/hook_event.h
@@ -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 */
diff --git a/usr/src/uts/common/sys/hook_impl.h b/usr/src/uts/common/sys/hook_impl.h
new file mode 100644
index 0000000000..d8e169b2ae
--- /dev/null
+++ b/usr/src/uts/common/sys/hook_impl.h
@@ -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 */
diff --git a/usr/src/uts/common/sys/neti.h b/usr/src/uts/common/sys/neti.h
new file mode 100644
index 0000000000..552ac25e93
--- /dev/null
+++ b/usr/src/uts/common/sys/neti.h
@@ -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 */
diff --git a/usr/src/uts/common/sys/queue.h b/usr/src/uts/common/sys/queue.h
new file mode 100644
index 0000000000..cb814390a9
--- /dev/null
+++ b/usr/src/uts/common/sys/queue.h
@@ -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 */
diff --git a/usr/src/uts/common/sys/stream.h b/usr/src/uts/common/sys/stream.h
index cb5a92b7d3..642cd276bf 100644
--- a/usr/src/uts/common/sys/stream.h
+++ b/usr/src/uts/common/sys/stream.h
@@ -393,8 +393,8 @@ typedef struct bcache {
/*
* 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:
diff --git a/usr/src/uts/intel/Makefile.intel.shared b/usr/src/uts/intel/Makefile.intel.shared
index e0064013fe..2c3f70e909 100644
--- a/usr/src/uts/intel/Makefile.intel.shared
+++ b/usr/src/uts/intel/Makefile.intel.shared
@@ -258,7 +258,6 @@ DRV_KMODS += mm
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 += fssnap_if
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 += mac
MISC_KMODS += mixer
MISC_KMODS += nfs_dlboot
MISC_KMODS += nfssrv
+MISC_KMODS += neti
MISC_KMODS += pcicfg
MISC_KMODS += pcihp
MISC_KMODS += pcmcia
diff --git a/usr/src/uts/intel/arp/Makefile b/usr/src/uts/intel/arp/Makefile
index ba352e8dc8..62adad839b 100644
--- a/usr/src/uts/intel/arp/Makefile
+++ b/usr/src/uts/intel/arp/Makefile
@@ -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 @@ INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOTLINK) $(ROOT_CONFFILE)
#
# depends on ip
#
-LDFLAGS += -dy -Ndrv/ip
+LDFLAGS += -dy -Ndrv/ip -Ndrv/hook -Nmisc/neti
#
# Default build targets.
diff --git a/usr/src/uts/intel/pfil/Makefile b/usr/src/uts/intel/hook/Makefile
index 14556577bf..9fa6442003 100644
--- a/usr/src/uts/intel/pfil/Makefile
+++ b/usr/src/uts/intel/hook/Makefile
@@ -19,17 +19,16 @@
# 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"
#
-# uts/intel/pfil/Makefile
-#
-# This makefile drives the production of the pfil driver
-# kernel module.
+# This makefile drives the production of the hook driver kernel module.
#
-# intel architecture dependent
+# INTEL implementation architecture dependent
#
#
@@ -40,12 +39,11 @@ 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
+MODULE = hook
+OBJECTS = $(HOOK_OBJS:%=$(OBJS_DIR)/%)
+LINTS = $(HOOK_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE = $(ROOT_MISC_DIR)/$(MODULE)
+
#
# Include common rules.
@@ -55,13 +53,10 @@ include $(UTSBASE)/intel/Makefile.intel
#
# Define targets
#
-ALL_TARGET = $(BINARY) $(SRC_CONFFILE)
+ALL_TARGET = $(BINARY)
LINT_TARGET = $(MODULE).lint
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOTLINK) $(ROOT_CONFFILE)
+INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOTLINK)
-MINOR= echo $(RELEASE) | cut -d. -f2
-CPPFLAGS += -DSUNDDI -DSOLARIS2=$(MINOR:sh) -DIRE_ILL_CN -DSOLARIS -DUSE_INET6
-LDFLAGS += -dy -Ndrv/ip
#
# Default build targets.
@@ -84,8 +79,6 @@ clean.lint: $(CLEAN_LINT_DEPS)
install: $(INSTALL_DEPS)
-$(ROOTLINK): $(ROOT_STRMOD_DIR) $(ROOTMODULE)
- -$(RM) $@; ln $(ROOTMODULE) $@
#
# Include common targets.
diff --git a/usr/src/uts/intel/ip/Makefile b/usr/src/uts/intel/ip/Makefile
index f1af1c3d9e..2df8555cce 100644
--- a/usr/src/uts/intel/ip/Makefile
+++ b/usr/src/uts/intel/ip/Makefile
@@ -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 @@ CFLAGS += $(CINLINEFLAGS)
# 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.
diff --git a/usr/src/uts/intel/ipf/Makefile b/usr/src/uts/intel/ipf/Makefile
index 84d447a2cc..122a9d66f7 100644
--- a/usr/src/uts/intel/ipf/Makefile
+++ b/usr/src/uts/intel/ipf/Makefile
@@ -1,4 +1,24 @@
#
+# 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 @@ INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
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
diff --git a/usr/src/uts/intel/neti/Makefile b/usr/src/uts/intel/neti/Makefile
new file mode 100644
index 0000000000..069cacc8d2
--- /dev/null
+++ b/usr/src/uts/intel/neti/Makefile
@@ -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
diff --git a/usr/src/uts/intel/os/device_policy b/usr/src/uts/intel/os/device_policy
index 77d9b9520f..184ac3454d 100644
--- a/usr/src/uts/intel/os/device_policy
+++ b/usr/src/uts/intel/os/device_policy
@@ -84,5 +84,4 @@ aggr:ctl read_priv_set=sys_net_config write_priv_set=sys_net_config
# 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
diff --git a/usr/src/uts/intel/os/minor_perm b/usr/src/uts/intel/os/minor_perm
index 3929c6f960..582bdecb60 100644
--- a/usr/src/uts/intel/os/minor_perm
+++ b/usr/src/uts/intel/os/minor_perm
@@ -107,7 +107,6 @@ ramdisk:ctl 0644 root sys
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
diff --git a/usr/src/uts/intel/os/name_to_major b/usr/src/uts/intel/os/name_to_major
index 1bd224f2d5..9133b5f4d3 100644
--- a/usr/src/uts/intel/os/name_to_major
+++ b/usr/src/uts/intel/os/name_to_major
@@ -98,7 +98,6 @@ bscv 161
pool 163
zcons 164
ipf 165
-pfil 166
fasttrap 167
bl 168
mpt 169
diff --git a/usr/src/uts/sparc/Makefile.sparc.shared b/usr/src/uts/sparc/Makefile.sparc.shared
index 0aee1eae57..2f9a657cbd 100644
--- a/usr/src/uts/sparc/Makefile.sparc.shared
+++ b/usr/src/uts/sparc/Makefile.sparc.shared
@@ -234,7 +234,7 @@ DRV_KMODS += spdsock
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 += ibcm
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
diff --git a/usr/src/uts/sparc/arp/Makefile b/usr/src/uts/sparc/arp/Makefile
index 80ca383b2c..6f97e434d1 100644
--- a/usr/src/uts/sparc/arp/Makefile
+++ b/usr/src/uts/sparc/arp/Makefile
@@ -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 @@ CFLAGS += $(CCVERBOSE)
#
# depends on ip
#
-LDFLAGS += -dy -Ndrv/ip
+LDFLAGS += -dy -Ndrv/ip -Ndrv/hook -Nmisc/neti
#
# Default build targets.
diff --git a/usr/src/uts/sparc/hook/Makefile b/usr/src/uts/sparc/hook/Makefile
new file mode 100644
index 0000000000..53a95c8d1b
--- /dev/null
+++ b/usr/src/uts/sparc/hook/Makefile
@@ -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
diff --git a/usr/src/uts/sparc/ip/Makefile b/usr/src/uts/sparc/ip/Makefile
index aff0025a14..150ebca372 100644
--- a/usr/src/uts/sparc/ip/Makefile
+++ b/usr/src/uts/sparc/ip/Makefile
@@ -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 @@ CFLAGS += -xinline=tcp_set_ws_value
# 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.
diff --git a/usr/src/uts/sparc/ipf/Makefile b/usr/src/uts/sparc/ipf/Makefile
index c0400bb4c4..0fedfdc8a9 100644
--- a/usr/src/uts/sparc/ipf/Makefile
+++ b/usr/src/uts/sparc/ipf/Makefile
@@ -1,4 +1,24 @@
#
+# 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 @@ MINOR= echo $(RELEASE) | cut -d. -f2
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
diff --git a/usr/src/uts/sparc/pfil/Makefile b/usr/src/uts/sparc/neti/Makefile
index fae0500ce1..9b5985c734 100644
--- a/usr/src/uts/sparc/pfil/Makefile
+++ b/usr/src/uts/sparc/neti/Makefile
@@ -19,17 +19,16 @@
# 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"
#
-# uts/sparc/pfil/Makefile
-#
-# This makefile drives the production of the pfil driver
-# kernel module.
+# This makefile drives the production of the neti driver kernel module.
#
-# sparc architecture dependent
+# SPARC implementation architecture dependent
#
#
@@ -40,12 +39,10 @@ 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
+MODULE = neti
+OBJECTS = $(NETI_OBJS:%=$(OBJS_DIR)/%)
+LINTS = $(NETI_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE = $(ROOT_MISC_DIR)/$(MODULE)
#
# Include common rules.
@@ -55,17 +52,16 @@ include $(UTSBASE)/sparc/Makefile.sparc
#
# Define targets
#
-ALL_TARGET = $(BINARY) $(SRC_CONFFILE)
+ALL_TARGET = $(BINARY)
LINT_TARGET = $(MODULE).lint
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOTLINK) $(ROOT_CONFFILE)
+INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOTLINK)
#
-# lint pass one enforcement and OS version
+# lint pass one enforcement
#
-MINOR= echo $(RELEASE) | cut -d. -f2
CFLAGS += $(CCVERBOSE)
-CPPFLAGS += -DSUNDDI -DSOLARIS2=$(MINOR:sh) -DIRE_ILL_CN -DSOLARIS -DUSE_INET6
-LDFLAGS += -dy -Ndrv/ip
+
+LDFLAGS += -dy -Nmisc/hook
#
# Default build targets.
@@ -82,15 +78,12 @@ clobber: $(CLOBBER_DEPS)
lint: $(LINT_DEPS)
-modlintlib: $(MODLINTLIB_DEPS) lint64
+modlintlib: $(MODLINTLIB_DEPS)
clean.lint: $(CLEAN_LINT_DEPS)
install: $(INSTALL_DEPS)
-$(ROOTLINK): $(ROOT_STRMOD_DIR) $(ROOTMODULE)
- -$(RM) $@; ln $(ROOTMODULE) $@
-
#
# Include common targets.
#
diff --git a/usr/src/uts/sparc/os/device_policy b/usr/src/uts/sparc/os/device_policy
index dc961eaccb..0e8e3f5b13 100644
--- a/usr/src/uts/sparc/os/device_policy
+++ b/usr/src/uts/sparc/os/device_policy
@@ -90,5 +90,4 @@ aggr:ctl read_priv_set=sys_net_config write_priv_set=sys_net_config
# 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
diff --git a/usr/src/uts/sparc/os/minor_perm b/usr/src/uts/sparc/os/minor_perm
index 7c5c275982..bd165cbef9 100644
--- a/usr/src/uts/sparc/os/minor_perm
+++ b/usr/src/uts/sparc/os/minor_perm
@@ -136,7 +136,6 @@ ramdisk:ctl 0644 root sys
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
diff --git a/usr/src/uts/sparc/os/name_to_major b/usr/src/uts/sparc/os/name_to_major
index 6953ae6833..f500ac8dca 100644
--- a/usr/src/uts/sparc/os/name_to_major
+++ b/usr/src/uts/sparc/os/name_to_major
@@ -175,7 +175,6 @@ todds1307 225
pool 226
zcons 227
ipf 228
-pfil 229
ctsmc 230
bl 231
ibd 232