summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/ipf/lib/common/load_hash.c9
-rw-r--r--usr/src/cmd/ipf/lib/common/load_hashnode.c9
-rw-r--r--usr/src/cmd/ipf/lib/common/load_pool.c9
-rw-r--r--usr/src/cmd/ipf/lib/common/load_poolnode.c7
-rw-r--r--usr/src/cmd/ipf/tools/Makefile.tools16
-rw-r--r--usr/src/cmd/ipf/tools/ipf.c43
-rw-r--r--usr/src/cmd/ipf/tools/ipfs.c36
-rw-r--r--usr/src/cmd/ipf/tools/ipfstat.c38
-rw-r--r--usr/src/cmd/ipf/tools/ipfzone.c161
-rw-r--r--usr/src/cmd/ipf/tools/ipfzone.h17
-rw-r--r--usr/src/cmd/ipf/tools/ipmon.c37
-rw-r--r--usr/src/cmd/ipf/tools/ipnat.c19
-rw-r--r--usr/src/cmd/ipf/tools/ippool.c92
-rw-r--r--usr/src/man/man1m/ipf.1m45
-rw-r--r--usr/src/man/man1m/ipfs.1m49
-rw-r--r--usr/src/man/man1m/ipfstat.1m35
-rw-r--r--usr/src/man/man1m/ipmon.1m38
-rw-r--r--usr/src/man/man1m/ipnat.1m37
-rw-r--r--usr/src/man/man1m/ippool.1m56
-rw-r--r--usr/src/man/man5/ipfilter.5103
-rw-r--r--usr/src/uts/common/inet/ipf/fil.c53
-rw-r--r--usr/src/uts/common/inet/ipf/ip_fil_solaris.c225
-rw-r--r--usr/src/uts/common/inet/ipf/ip_log.c10
-rw-r--r--usr/src/uts/common/inet/ipf/ip_state.c2
-rw-r--r--usr/src/uts/common/inet/ipf/netinet/ip_fil.h30
-rw-r--r--usr/src/uts/common/inet/ipf/netinet/ipf_stack.h4
-rw-r--r--usr/src/uts/common/inet/ipf/solaris.c215
-rw-r--r--usr/src/uts/intel/ipf/ipf.global-objs.debug6424
-rw-r--r--usr/src/uts/sparc/ipf/ipf.global-objs.debug6426
29 files changed, 1236 insertions, 209 deletions
diff --git a/usr/src/cmd/ipf/lib/common/load_hash.c b/usr/src/cmd/ipf/lib/common/load_hash.c
index e43ddf54a3..ef65c26b75 100644
--- a/usr/src/cmd/ipf/lib/common/load_hash.c
+++ b/usr/src/cmd/ipf/lib/common/load_hash.c
@@ -7,15 +7,16 @@
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <fcntl.h>
#include <sys/ioctl.h>
#include "ipf.h"
#include "netinet/ip_lookup.h"
#include "netinet/ip_htable.h"
+#include "ipfzone.h"
static int hashfd = -1;
@@ -35,6 +36,10 @@ ioctlfunc_t iocfunc;
hashfd = open(IPLOOKUP_NAME, O_RDWR);
if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0))
return -1;
+ if (setzone(hashfd) != 0) {
+ close(hashfd);
+ return -1;
+ }
for (n = 0, a = list; a != NULL; a = a->ipe_next)
n++;
diff --git a/usr/src/cmd/ipf/lib/common/load_hashnode.c b/usr/src/cmd/ipf/lib/common/load_hashnode.c
index 8cf1bb2c67..d408d511c2 100644
--- a/usr/src/cmd/ipf/lib/common/load_hashnode.c
+++ b/usr/src/cmd/ipf/lib/common/load_hashnode.c
@@ -7,15 +7,16 @@
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <fcntl.h>
#include <sys/ioctl.h>
#include "ipf.h"
#include "netinet/ip_lookup.h"
#include "netinet/ip_htable.h"
+#include "ipfzone.h"
static int hashfd = -1;
@@ -34,6 +35,10 @@ ioctlfunc_t iocfunc;
hashfd = open(IPLOOKUP_NAME, O_RDWR);
if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0))
return -1;
+ if (setzone(hashfd) != 0) {
+ close(hashfd);
+ return -1;
+ }
op.iplo_type = IPLT_HASH;
op.iplo_unit = unit;
diff --git a/usr/src/cmd/ipf/lib/common/load_pool.c b/usr/src/cmd/ipf/lib/common/load_pool.c
index b8146c060c..ba246bb449 100644
--- a/usr/src/cmd/ipf/lib/common/load_pool.c
+++ b/usr/src/cmd/ipf/lib/common/load_pool.c
@@ -7,15 +7,16 @@
*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <fcntl.h>
#include <sys/ioctl.h>
#include "ipf.h"
#include "netinet/ip_lookup.h"
#include "netinet/ip_pool.h"
+#include "ipfzone.h"
static int poolfd = -1;
@@ -32,6 +33,10 @@ ioctlfunc_t iocfunc;
poolfd = open(IPLOOKUP_NAME, O_RDWR);
if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0))
return -1;
+ if (setzone(poolfd) != 0) {
+ close(poolfd);
+ return -1;
+ }
op.iplo_unit = plp->ipo_unit;
op.iplo_type = IPLT_POOL;
diff --git a/usr/src/cmd/ipf/lib/common/load_poolnode.c b/usr/src/cmd/ipf/lib/common/load_poolnode.c
index e992a80281..4203f0faa5 100644
--- a/usr/src/cmd/ipf/lib/common/load_poolnode.c
+++ b/usr/src/cmd/ipf/lib/common/load_poolnode.c
@@ -4,6 +4,8 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
* $Id: load_poolnode.c,v 1.3.2.1 2004/03/06 14:33:29 darrenr Exp $
+ *
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
*/
#include <fcntl.h>
@@ -11,6 +13,7 @@
#include "ipf.h"
#include "netinet/ip_lookup.h"
#include "netinet/ip_pool.h"
+#include "ipfzone.h"
static int poolfd = -1;
@@ -29,6 +32,10 @@ ioctlfunc_t iocfunc;
poolfd = open(IPLOOKUP_NAME, O_RDWR);
if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0))
return -1;
+ if (setzone(poolfd) != 0) {
+ close(poolfd);
+ return -1;
+ }
op.iplo_unit = role;
op.iplo_type = IPLT_POOL;
diff --git a/usr/src/cmd/ipf/tools/Makefile.tools b/usr/src/cmd/ipf/tools/Makefile.tools
index 5d8bee1d04..7c1e151762 100644
--- a/usr/src/cmd/ipf/tools/Makefile.tools
+++ b/usr/src/cmd/ipf/tools/Makefile.tools
@@ -24,17 +24,19 @@
#
# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
#
+# Copyright (c) 2012, Joyent Inc. All rights reserved.
+#
PROG= ipf ipfs ipmon ipnat ippool ipfstat
IPFPROG= ipftest
-IPF_OBJS= ipf.o ipfcomp.o ipf_y.o ipf_l.o
-IPFS_OBJS= ipfs.o
-IPFSTAT_OBJS= ipfstat.o
-IPMON_OBJS= ipmon.o ipmon_y.o ipmon_l.o
-IPNAT_OBJS= ipnat.o ipnat_y.o ipnat_l.o
-IPPOOL_OBJS= ippool.o ippool_y.o ippool_l.o
-IPFTEST_OBJS= ipftest.o \
+IPF_OBJS= ipf.o ipfcomp.o ipfzone.o ipf_y.o ipf_l.o
+IPFS_OBJS= ipfs.o ipfzone.o
+IPFSTAT_OBJS= ipfstat.o ipfzone.o
+IPMON_OBJS= ipmon.o ipfzone.o ipmon_y.o ipmon_l.o
+IPNAT_OBJS= ipnat.o ipfzone.o ipnat_y.o ipnat_l.o
+IPPOOL_OBJS= ippool.o ipfzone.o ippool_y.o ippool_l.o
+IPFTEST_OBJS= ipftest.o ipfzone.o \
ip_fil.o ip_state.o ip_compat.o \
ip_frag.o ip_nat.o ip_nat6.o fil.o \
ip_htable.o ip_lookup.o \
diff --git a/usr/src/cmd/ipf/tools/ipf.c b/usr/src/cmd/ipf/tools/ipf.c
index e81389b342..7a664c80e6 100644
--- a/usr/src/cmd/ipf/tools/ipf.c
+++ b/usr/src/cmd/ipf/tools/ipf.c
@@ -5,6 +5,8 @@
*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
*/
#ifdef __FreeBSD__
@@ -20,6 +22,7 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include "netinet/ipl.h"
+#include "ipfzone.h"
#if !defined(lint)
static const char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-2000 Darren Reed";
@@ -62,9 +65,9 @@ static ioctlfunc_t iocfunctions[IPL_LOGSIZE] = { ioctl, ioctl, ioctl,
static void usage()
{
- fprintf(stderr, "usage: ipf [-6AdDEInoPrRsvVyzZ] %s %s %s\n",
+ fprintf(stderr, "usage: ipf [-6AdDEGInoPrRsvVyzZ] %s %s %s",
"[-l block|pass|nomatch|state|nat]", "[-cc] [-F i|o|a|s|S|u]",
- "[-f filename] [-T <tuneopts>]");
+ "[-f filename] [-T <tuneopts>] [zonename]\n");
exit(1);
}
@@ -74,11 +77,21 @@ int argc;
char *argv[];
{
int c;
+ const char *optstr = "6Ac:dDEf:F:GIl:noPrRsT:vVyzZ";
if (argc < 2)
usage();
- while ((c = getopt(argc, argv, "6Ac:dDEf:F:Il:noPrRsT:vVyzZ")) != -1) {
+ /*
+ * We need to set the zone name before calling the functions
+ * in the switch statement below. Note that ipf.c differs from the other
+ * tools in the ipfilter suite: the zone name is specified as the
+ * last argument, while the other tools use the -z option. ipf
+ * already has a -z option, so the last argument is used instead.
+ */
+ getzonearg(argc, argv, optstr);
+
+ while ((c = getopt(argc, argv, optstr)) != -1) {
switch (c)
{
case '?' :
@@ -111,6 +124,9 @@ char *argv[];
case 'F' :
flushfilter(optarg);
break;
+ case 'G' :
+ /* Already handled by getzonearg() above */
+ break;
case 'I' :
opts ^= OPT_INACTIVE;
break;
@@ -187,6 +203,12 @@ int check;
if ((fd = open(ipfdev, O_RDWR)) == -1)
if ((fd = open(ipfdev, O_RDONLY)) == -1)
perror("open device");
+
+ if (setzone(fd) != 0) {
+ close(fd);
+ return -2;
+ }
+
return fd;
}
@@ -307,6 +329,11 @@ char *opt;
if (opts & OPT_VERBOSE)
printf("set state log flag\n");
xfd = open(IPSTATE_NAME, O_RDWR);
+ if (xfd >= 0 && setzone(xfd) != 0) {
+ close(xfd);
+ xfd = -1;
+ }
+
if (xfd >= 0) {
logopt = 0;
if (ioctl(xfd, SIOCGETLG, &logopt))
@@ -324,6 +351,11 @@ char *opt;
if (opts & OPT_VERBOSE)
printf("set nat log flag\n");
xfd = open(IPNAT_NAME, O_RDWR);
+ if (xfd >= 0 && setzone(xfd) != 0) {
+ close(xfd);
+ xfd = -1;
+ }
+
if (xfd >= 0) {
logopt = 0;
if (ioctl(xfd, SIOCGETLG, &logopt))
@@ -516,6 +548,11 @@ static int showversion()
return 1;
}
+ if (setzone(vfd) != 0) {
+ close(vfd);
+ return 1;
+ }
+
if (ioctl(vfd, SIOCGETFS, &ipfo)) {
perror("ioctl(SIOCGETFS)");
close(vfd);
diff --git a/usr/src/cmd/ipf/tools/ipfs.c b/usr/src/cmd/ipf/tools/ipfs.c
index da8387324a..e84168e25d 100644
--- a/usr/src/cmd/ipf/tools/ipfs.c
+++ b/usr/src/cmd/ipf/tools/ipfs.c
@@ -5,6 +5,8 @@
*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
*/
#ifdef __FreeBSD__
@@ -44,6 +46,7 @@
#include <resolv.h>
#include "ipf.h"
#include "netinet/ipl.h"
+#include "ipfzone.h"
#if !defined(lint)
static const char rcsid[] = "@(#)Id: ipfs.c,v 1.12 2003/12/01 01:56:53 darrenr Exp";
@@ -86,14 +89,17 @@ char *progname;
void usage()
{
- fprintf(stderr, "usage: %s [-nv] -l\n", progname);
- fprintf(stderr, "usage: %s [-nv] -u\n", progname);
- fprintf(stderr, "usage: %s [-nv] [-d <dir>] -R\n", progname);
- fprintf(stderr, "usage: %s [-nv] [-d <dir>] -W\n", progname);
- fprintf(stderr, "usage: %s [-nv] [-N|-S] [-f <file>] -r\n", progname);
- fprintf(stderr, "usage: %s [-nv] [-N|-S] [-f <file>] -w\n", progname);
- fprintf(stderr, "usage: %s [-nv] [-N|-S] -f <file> -i <if1>,<if2>\n",
- progname);
+ const char *zoneopt = "[-G|-z zonename] ";
+ fprintf(stderr, "usage: %s %s[-nv] -l\n", progname, zoneopt);
+ fprintf(stderr, "usage: %s %s[-nv] -u\n", progname, zoneopt);
+ fprintf(stderr, "usage: %s %s[-nv] [-d <dir>] -R\n", progname, zoneopt);
+ fprintf(stderr, "usage: %s %s[-nv] [-d <dir>] -W\n", progname, zoneopt);
+ fprintf(stderr, "usage: %s %s[-nv] [-N|-S] [-f <file>] -r\n", progname,
+ zoneopt);
+ fprintf(stderr, "usage: %s %s[-nv] [-N|-S] [-f <file>] -w\n", progname,
+ zoneopt);
+ fprintf(stderr, "usage: %s %s[-nv] [-N|-S] -f <file> -i <if1>,<if2>\n",
+ progname, zoneopt);
exit(1);
}
@@ -218,7 +224,7 @@ char *argv[];
char *dirname = NULL, *filename = NULL, *ifs = NULL;
progname = argv[0];
- while ((c = getopt(argc, argv, "d:f:lNnSRruvWw")) != -1)
+ while ((c = getopt(argc, argv, "d:f:G:lNnSRruvWwz:")) != -1)
switch (c)
{
case 'd' :
@@ -233,6 +239,9 @@ char *argv[];
else
usage();
break;
+ case 'G' :
+ setzonename_global(optarg);
+ break;
case 'i' :
ifs = optarg;
set = 1;
@@ -287,6 +296,9 @@ char *argv[];
rw = 3;
set = 1;
break;
+ case 'z' :
+ setzonename(optarg);
+ break;
case '?' :
default :
usage();
@@ -355,6 +367,12 @@ char *ipfdev;
if ((fd = open(ipfdev, O_RDWR)) == -1)
if ((fd = open(ipfdev, O_RDONLY)) == -1)
perror("open device");
+
+ if (setzone(fd) != 0) {
+ close(fd);
+ fd = -1;
+ }
+
return fd;
}
diff --git a/usr/src/cmd/ipf/tools/ipfstat.c b/usr/src/cmd/ipf/tools/ipfstat.c
index 27b018e273..fd39556465 100644
--- a/usr/src/cmd/ipf/tools/ipfstat.c
+++ b/usr/src/cmd/ipf/tools/ipfstat.c
@@ -5,6 +5,8 @@
*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
*/
#ifdef __FreeBSD__
@@ -71,6 +73,7 @@
#if defined(__NetBSD__) || (__OpenBSD__)
# include <paths.h>
#endif
+#include "ipfzone.h"
#if !defined(lint)
static const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed";
@@ -177,6 +180,7 @@ char *name;
#else
fprintf(stderr, " %s -t [-C] ", name);
#endif
+ fprintf(stderr, "[-G|-z zonename] ");
fprintf(stderr, "[-D destination address] [-P protocol] [-S source address] [-T refresh time]\n");
exit(1);
}
@@ -207,9 +211,9 @@ char *argv[];
u_32_t frf;
#ifdef USE_INET6
- options = "6aACdfghIilnostvD:M:N:P:RS:T:";
+ options = "6aACdfgG:hIilnostvD:M:N:P:RS:T:z:";
#else
- options = "aACdfghIilnostvD:M:N:P:RS:T:";
+ options = "aACdfgG:hIilnostvD:M:N:P:RS:T:z:";
#endif
saddr.in4.s_addr = INADDR_ANY; /* default any v4 source addr */
@@ -223,13 +227,16 @@ char *argv[];
opterr = 0;
/*
- * Parse these two arguments now lest there be any buffer overflows
+ * Parse these four arguments now lest there be any buffer overflows
* in the parsing of the rest.
*/
myoptind = optind;
while ((c = getopt(argc, argv, options)) != -1) {
switch (c)
{
+ case 'G' :
+ setzonename_global(optarg);
+ break;
case 'M' :
memf = optarg;
live_kernel = 0;
@@ -238,6 +245,9 @@ char *argv[];
kern = optarg;
live_kernel = 0;
break;
+ case 'z' :
+ setzonename(optarg);
+ break;
}
}
optind = myoptind;
@@ -247,11 +257,22 @@ char *argv[];
perror("open(IPSTATE_NAME)");
exit(-1);
}
+
+ if (setzone(state_fd) != 0) {
+ close(state_fd);
+ exit(-1);
+ }
+
if ((ipf_fd = open(device, O_RDONLY)) == -1) {
fprintf(stderr, "open(%s)", device);
perror("");
exit(-1);
}
+
+ if (setzone(ipf_fd) != 0) {
+ close(ipf_fd);
+ exit(-1);
+ }
}
if (kern != NULL || memf != NULL) {
@@ -298,6 +319,9 @@ char *argv[];
case 'g' :
opts |= OPT_GROUPS;
break;
+ case 'G' :
+ /* Already handled by getzoneopt() above */
+ break;
case 'h' :
opts |= OPT_HITS;
break;
@@ -360,6 +384,9 @@ char *argv[];
opts |= OPT_VERBOSE;
opts |= OPT_UNDEF;
break;
+ case 'z' :
+ /* Already handled by getzoneopt() above */
+ break;
default :
usage(argv[0]);
break;
@@ -482,6 +509,11 @@ u_32_t *frfp;
exit(-1);
}
+ if (setzone(ipf_fd) != 0) {
+ close(ipf_fd);
+ exit(-1);
+ }
+
bzero((caddr_t)&ipfo, sizeof(ipfo));
ipfo.ipfo_rev = IPFILTER_VERSION;
ipfo.ipfo_size = sizeof(fr_authstat_t);
diff --git a/usr/src/cmd/ipf/tools/ipfzone.c b/usr/src/cmd/ipf/tools/ipfzone.c
new file mode 100644
index 0000000000..d4e1bb8427
--- /dev/null
+++ b/usr/src/cmd/ipf/tools/ipfzone.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2014 Joyent, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * See the IPFILTER.LICENCE file for details on licensing.
+ */
+
+
+#include <errno.h>
+#include <net/if.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <zone.h>
+
+#include "netinet/ip_fil.h"
+#include "ipfzone.h"
+
+static ipfzoneobj_t ipzo;
+static boolean_t do_setzone = 0;
+static int num_setzones = 0;
+
+extern int errno;
+extern int opterr;
+extern int optind;
+extern char *optarg;
+
+/*
+ * Get the zonename if it's the last argument and set the zonename
+ * in ipfzo to it. This is used by ipf(1m) only - all of the other tools
+ * specify the zone with the -z option, and therefore use getzoneopt() below.
+ */
+void
+getzonearg(int argc, char *argv[], const char *optstr)
+{
+ int c;
+
+ /*
+ * Don't warn about unknown options - let subsequent calls to
+ * getopt() handle this.
+ */
+ opterr = 0;
+
+ /*
+ * getopt is also used here to set optind so that we can
+ * determine if the last argument belongs to a flag or is
+ * actually a zonename.
+ */
+ while ((c = getopt(argc, argv, optstr)) != -1) {
+ if (c == 'G')
+ ipzo.ipfz_gz = 1;
+ }
+
+ if (optind < argc)
+ setzonename(argv[optind]);
+
+ /*
+ * Reset optind and opterr so the next getopt call will go through all
+ * of argv again and warn about unknown options.
+ */
+ optind = 1;
+ opterr = 1;
+}
+
+/*
+ * Get a -z option from argv and set the zonename in ipfzo accordingly
+ */
+void
+getzoneopt(int argc, char *argv[], const char *optstr)
+{
+ int c;
+
+ /*
+ * Don't warn about unknown options - let subsequent calls to
+ * getopt() handle this.
+ */
+ opterr = 0;
+
+ while ((c = getopt(argc, argv, optstr)) != -1) {
+ if (c == 'G')
+ setzonename_global(optarg);
+
+ if (c == 'z')
+ setzonename(optarg);
+ }
+
+ /*
+ * Reset optind and opterr so the next getopt call will go through all
+ * of argv again and warn about unknown options.
+ */
+ optind = 1;
+ opterr = 1;
+}
+
+/*
+ * Set the zonename in ipfzo to the given string: this is the zone all further
+ * ioctls will act on.
+ */
+void
+setzonename(const char *zonename)
+{
+ memcpy(ipzo.ipfz_zonename, zonename, sizeof (ipzo.ipfz_zonename));
+ do_setzone = B_TRUE;
+ num_setzones++;
+}
+
+/*
+ * Set the zonename in ipfo, and the gz flag. This indicates that we want all
+ * further ioctls to act on the GZ-controlled stack for that zone.
+ */
+void
+setzonename_global(const char *zonename)
+{
+ setzonename(zonename);
+ ipzo.ipfz_gz = 1;
+}
+
+/*
+ * Set the zone that all further ioctls will operate on. See the "GZ-controlled
+ * and per-zone stacks" note at the top of ip_fil_solaris.c for further
+ * explanation.
+ */
+int
+setzone(int fd)
+{
+ if (!do_setzone)
+ return (0);
+
+ if (num_setzones > 1) {
+ (void) fprintf(stderr,
+ "Only one of -G and -z may be set\n");
+ return (-1);
+ }
+
+ if (ipzo.ipfz_gz == 1 &&
+ getzoneidbyname(ipzo.ipfz_zonename) == GLOBAL_ZONEID) {
+ (void) fprintf(stderr,
+ "-G cannot be used with the global zone\n");
+ return (-1);
+ }
+
+ if (ioctl(fd, SIOCIPFZONESET, &ipzo) == -1) {
+ switch (errno) {
+ case ENODEV:
+ (void) fprintf(stderr,
+ "Could not find running zone: %s\n",
+ ipzo.ipfz_zonename);
+ break;
+ case EACCES:
+ (void) fprintf(stderr,
+ "Permission denied setting zone: %s\n",
+ ipzo.ipfz_zonename);
+ break;
+ default:
+ perror("Error setting zone");
+ }
+ return (-1);
+ }
+
+ return (0);
+}
diff --git a/usr/src/cmd/ipf/tools/ipfzone.h b/usr/src/cmd/ipf/tools/ipfzone.h
new file mode 100644
index 0000000000..ca6f42ec6a
--- /dev/null
+++ b/usr/src/cmd/ipf/tools/ipfzone.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * See the IPFILTER.LICENCE file for details on licensing.
+ */
+
+#ifndef __IPFZONE_H__
+#define __IPFZONE_H__
+
+void getzonearg(int, char *[], const char *);
+void getzoneopt(int, char *[], const char *);
+int setzone(int);
+void setzonename(const char *);
+void setzonename_global(const char *);
+
+#endif /* __IPFZONE_H__ */
diff --git a/usr/src/cmd/ipf/tools/ipmon.c b/usr/src/cmd/ipf/tools/ipmon.c
index d4a351b015..a91e23237a 100644
--- a/usr/src/cmd/ipf/tools/ipmon.c
+++ b/usr/src/cmd/ipf/tools/ipmon.c
@@ -5,6 +5,8 @@
*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
*/
@@ -78,6 +80,7 @@
#include "netinet/ip_state.h"
#include "netinet/ip_proxy.h"
#include "ipmon.h"
+#include "ipfzone.h"
#if !defined(lint)
static const char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed";
@@ -1340,10 +1343,10 @@ printipflog:
static void usage(prog)
char *prog;
{
- fprintf(stderr, "%s: [-abDFhnpstvxX] %s %s %s %s %s %s\n",
- prog, "[-N device]", "[ [-o [NSI]] [-O [NSI]]",
- "[-P pidfile]", "[-S device]", "[-f device]",
- "filename");
+ fprintf(stderr, "%s: [-abDFhnpstvxX] %s %s %s %s %s %s %s\n",
+ prog, "[-G|-z zonename]", "[-N device]",
+ "[ [-o [NSI]] [-O [NSI]]", "[-P pidfile]", "[-S device]",
+ "[-f device]", "filename");
exit(1);
}
@@ -1380,6 +1383,11 @@ FILE *log;
exit(1);
}
+ if (setzone(fd) != 0) {
+ close(fd);
+ exit(1);
+ }
+
if (ioctl(fd, SIOCIPFFB, &flushed) == 0) {
printf("%d bytes flushed from log buffer\n",
flushed);
@@ -1444,6 +1452,7 @@ char *argv[];
char buf[DEFAULT_IPFLOGSIZE], *iplfile[3], *s;
extern int optind;
extern char *optarg;
+ const char *optstr = "?abB:C:Df:G:FhnN:o:O:pP:sS:tvxXz:";
fd[0] = fd[1] = fd[2] = -1;
fdt[0] = fdt[1] = fdt[2] = -1;
@@ -1451,7 +1460,13 @@ char *argv[];
iplfile[1] = IPNAT_NAME;
iplfile[2] = IPSTATE_NAME;
- while ((c = getopt(argc, argv, "?abB:C:Df:FhnN:o:O:pP:sS:tvxX")) != -1)
+ /*
+ * We need to set the zone name before calling openlog in
+ * the switch statement below
+ */
+ getzoneopt(argc, argv, optstr);
+
+ while ((c = getopt(argc, argv, optstr)) != -1)
switch (c)
{
case 'a' :
@@ -1483,6 +1498,9 @@ char *argv[];
flushlogs(iplfile[1], log);
flushlogs(iplfile[2], log);
break;
+ case 'G' :
+ /* Already handled by getzoneopt() above */
+ break;
case 'n' :
opts |= OPT_RESOLVE;
break;
@@ -1535,6 +1553,9 @@ char *argv[];
case 'X' :
opts |= OPT_HEXHDR;
break;
+ case 'z' :
+ /* Already handled by getzoneopt() above */
+ break;
default :
case 'h' :
case '?' :
@@ -1571,6 +1592,12 @@ char *argv[];
exit(1);
/* NOTREACHED */
}
+
+ if (setzone(fd[i]) != 0) {
+ close(fd[i]);
+ exit(1);
+ }
+
if (!(regular[i] = !S_ISCHR(sb.st_mode)))
devices++;
}
diff --git a/usr/src/cmd/ipf/tools/ipnat.c b/usr/src/cmd/ipf/tools/ipnat.c
index 4a9a37a4a9..3a2610a235 100644
--- a/usr/src/cmd/ipf/tools/ipnat.c
+++ b/usr/src/cmd/ipf/tools/ipnat.c
@@ -7,6 +7,8 @@
*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
*/
#include <stdio.h>
@@ -55,6 +57,7 @@
#include "ipf.h"
#include "netinet/ipl.h"
#include "kmem.h"
+#include "ipfzone.h"
#ifdef __hpux
# define nlist nlist64
@@ -95,7 +98,8 @@ int opts;
void usage(name)
char *name;
{
- fprintf(stderr, "Usage: %s [-CdFhlnrRsv] [-f filename]\n", name);
+ fprintf(stderr, "Usage: %s [-CdFhlnrRsv] [-f filename]", name);
+ fprintf(stderr, " [-G|-z zonename]\n");
exit(1);
}
@@ -117,7 +121,7 @@ char *argv[];
kernel = NULL;
mode = O_RDWR;
- while ((c = getopt(argc, argv, "CdFf:hlM:N:nrRsv")) != -1)
+ while ((c = getopt(argc, argv, "CdFf:G:hlM:N:nrRsvz:")) != -1)
switch (c)
{
case 'C' :
@@ -132,6 +136,9 @@ char *argv[];
case 'F' :
opts |= OPT_FLUSH;
break;
+ case 'G' :
+ setzonename_global(optarg);
+ break;
case 'h' :
opts |=OPT_HITS;
break;
@@ -162,6 +169,9 @@ char *argv[];
case 'v' :
opts |= OPT_VERBOSE;
break;
+ case 'z' :
+ setzonename(optarg);
+ break;
default :
usage(argv[0]);
}
@@ -195,6 +205,11 @@ char *argv[];
exit(1);
}
+ if (setzone(fd) != 0) {
+ close(fd);
+ exit(1);
+ }
+
bzero((char *)&obj, sizeof(obj));
obj.ipfo_rev = IPFILTER_VERSION;
obj.ipfo_size = sizeof(*nsp);
diff --git a/usr/src/cmd/ipf/tools/ippool.c b/usr/src/cmd/ipf/tools/ippool.c
index 5f18379420..d0296139a8 100644
--- a/usr/src/cmd/ipf/tools/ippool.c
+++ b/usr/src/cmd/ipf/tools/ippool.c
@@ -5,10 +5,10 @@
*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/time.h>
#include <sys/param.h>
@@ -41,6 +41,7 @@
#include "netinet/ip_pool.h"
#include "netinet/ip_htable.h"
#include "kmem.h"
+#include "ipfzone.h"
extern int ippool_yyparse __P((void));
extern int ippool_yydebug;
@@ -71,15 +72,21 @@ int use_inet6 = 0;
void usage(prog)
char *prog;
{
+ const char *zoneopt = "[-G|-z zonename] ";
fprintf(stderr, "Usage:\t%s\n", prog);
- fprintf(stderr, "\t\t\t-a [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n");
- fprintf(stderr, "\t\t\t-A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n");
- fprintf(stderr, "\t\t\t-f <file> [-dnuv]\n");
- fprintf(stderr, "\t\t\t-F [-dv] [-o <role>] [-t <type>]\n");
- fprintf(stderr, "\t\t\t-l [-dv] [-m <name>] [-t <type>]\n");
- fprintf(stderr, "\t\t\t-r [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n");
- fprintf(stderr, "\t\t\t-R [-dnv] [-m <name>] [-o <role>] [-t <type>]\n");
- fprintf(stderr, "\t\t\t-s [-dtv] [-M <core>] [-N <namelist>]\n");
+ fprintf(stderr, "\t\t\t-a [-dnv] %s[-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n",
+ zoneopt);
+ fprintf(stderr, "\t\t\t-A [-dnv] %s[-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n",
+ zoneopt);
+ fprintf(stderr, "\t\t\t-f <file> %s[-dnuv]\n", zoneopt);
+ fprintf(stderr, "\t\t\t-F [-dv] %s[-o <role>] [-t <type>]\n", zoneopt);
+ fprintf(stderr, "\t\t\t-l [-dv] %s[-m <name>] [-t <type>]\n", zoneopt);
+ fprintf(stderr, "\t\t\t-r [-dnv] %s[-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n",
+ zoneopt);
+ fprintf(stderr, "\t\t\t-R [-dnv] %s[-m <name>] [-o <role>] [-t <type>]\n",
+ zoneopt);
+ fprintf(stderr, "\t\t\t-s [-dtv] %s[-M <core>] [-N <namelist>]\n",
+ zoneopt);
exit(1);
}
@@ -140,13 +147,16 @@ char *argv[];
role = IPL_LOGIPF;
bzero((char *)&node, sizeof(node));
- while ((c = getopt(argc, argv, "di:m:no:Rv")) != -1)
+ while ((c = getopt(argc, argv, "di:G:m:no:Rvz:")) != -1)
switch (c)
{
case 'd' :
opts |= OPT_DEBUG;
ippool_yydebug++;
break;
+ case 'G' :
+ setzonename_global(optarg);
+ break;
case 'i' :
s = strchr(optarg, '/');
if (s == NULL)
@@ -182,6 +192,9 @@ char *argv[];
case 'v' :
opts |= OPT_VERBOSE;
break;
+ case 'z' :
+ setzonename(optarg);
+ break;
}
if (opts & OPT_DEBUG)
@@ -219,13 +232,16 @@ char *argv[];
bzero((char *)&iph, sizeof(iph));
bzero((char *)&pool, sizeof(pool));
- while ((c = getopt(argc, argv, "dm:no:RS:t:v")) != -1)
+ while ((c = getopt(argc, argv, "dG:m:no:RS:t:vz:")) != -1)
switch (c)
{
case 'd' :
opts |= OPT_DEBUG;
ippool_yydebug++;
break;
+ case 'G' :
+ setzonename_global(optarg);
+ break;
case 'm' :
poolname = optarg;
break;
@@ -255,6 +271,9 @@ char *argv[];
case 'v' :
opts |= OPT_VERBOSE;
break;
+ case 'z' :
+ setzonename(optarg);
+ break;
}
if (opts & OPT_DEBUG)
@@ -308,13 +327,16 @@ char *argv[], *infile;
infile = optarg;
- while ((c = getopt(argc, argv, "dnRuv")) != -1)
+ while ((c = getopt(argc, argv, "dG:nRuvz:")) != -1)
switch (c)
{
case 'd' :
opts |= OPT_DEBUG;
ippool_yydebug++;
break;
+ case 'G' :
+ setzonename_global(optarg);
+ break;
case 'n' :
opts |= OPT_DONOTHING;
break;
@@ -327,6 +349,9 @@ char *argv[], *infile;
case 'v' :
opts |= OPT_VERBOSE;
break;
+ case 'z' :
+ setzonename(optarg);
+ break;
}
if (opts & OPT_DEBUG)
@@ -338,6 +363,11 @@ char *argv[], *infile;
perror("open(IPLOOKUP_NAME)");
exit(1);
}
+
+ if (setzone(fd) != 0) {
+ close(fd);
+ exit(1);
+ }
}
if (ippool_parsefile(fd, infile, ioctl) != 0)
@@ -365,12 +395,15 @@ char *argv[];
poolname = NULL;
role = IPL_LOGALL;
- while ((c = getopt(argc, argv, "dm:M:N:o:Rt:v")) != -1)
+ while ((c = getopt(argc, argv, "dG:m:M:N:o:Rt:vz:")) != -1)
switch (c)
{
case 'd' :
opts |= OPT_DEBUG;
break;
+ case 'G' :
+ setzonename_global(optarg);
+ break;
case 'm' :
poolname = optarg;
break;
@@ -402,6 +435,9 @@ char *argv[];
case 'v' :
opts |= OPT_VERBOSE;
break;
+ case 'z' :
+ setzonename(optarg);
+ break;
}
if (opts & OPT_DEBUG)
@@ -413,6 +449,11 @@ char *argv[];
perror("open(IPLOOKUP_NAME)");
exit(1);
}
+
+ if (setzone(fd) != 0) {
+ close(fd);
+ exit(1);
+ }
}
bzero((char *)&op, sizeof(op));
@@ -615,12 +656,15 @@ char *argv[];
bzero((char *)&op, sizeof(op));
- while ((c = getopt(argc, argv, "dM:N:o:t:v")) != -1)
+ while ((c = getopt(argc, argv, "dG:M:N:o:t:vz:")) != -1)
switch (c)
{
case 'd' :
opts |= OPT_DEBUG;
break;
+ case 'G' :
+ setzonename_global(optarg);
+ break;
case 'M' :
live_kernel = 0;
core = optarg;
@@ -647,6 +691,9 @@ char *argv[];
case 'v' :
opts |= OPT_VERBOSE;
break;
+ case 'z' :
+ setzonename(optarg);
+ break;
}
if (opts & OPT_DEBUG)
@@ -658,6 +705,11 @@ char *argv[];
perror("open(IPLOOKUP_NAME)");
exit(1);
}
+
+ if (setzone(fd) != 0) {
+ close(fd);
+ exit(1);
+ }
}
if (type == IPLT_ALL || type == IPLT_POOL) {
@@ -705,7 +757,7 @@ char *argv[];
type = IPLT_ALL;
role = IPL_LOGALL;
- while ((c = getopt(argc, argv, "do:t:v")) != -1)
+ while ((c = getopt(argc, argv, "do:t:vz:")) != -1)
switch (c)
{
case 'd' :
@@ -728,6 +780,9 @@ char *argv[];
case 'v' :
opts |= OPT_VERBOSE;
break;
+ case 'z' :
+ setzonename(optarg);
+ break;
}
if (opts & OPT_DEBUG)
@@ -739,6 +794,11 @@ char *argv[];
perror("open(IPLOOKUP_NAME)");
exit(1);
}
+
+ if (setzone(fd) != 0) {
+ close(fd);
+ exit(1);
+ }
}
bzero((char *)&flush, sizeof(flush));
diff --git a/usr/src/man/man1m/ipf.1m b/usr/src/man/man1m/ipf.1m
index 69cdacf689..57a3f4bb9a 100644
--- a/usr/src/man/man1m/ipf.1m
+++ b/usr/src/man/man1m/ipf.1m
@@ -2,19 +2,19 @@
.\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed
.\" location.
.\" Portions Copyright (c) 2009, Sun Microsystems Inc. All Rights Reserved.
-.TH IPF 1M "Feb 25, 2009"
+.\" Portions Copyright (c) 2014, Joyent, Inc. All Rights Reserved.
+.TH IPF 1M "Oct 7, 2014"
.SH NAME
ipf \- alter packet filtering lists for IP packet input and output
.SH SYNOPSIS
.LP
.nf
-\fBipf\fR [\fB-6AdDEInoPRrsvVyzZ\fR] [\fB-l\fR block | pass | nomatch]
+\fBipf\fR [\fB-6AdDEGInoPRrsvVyzZ\fR] [\fB-l\fR block | pass | nomatch]
[\fB-T\fR \fIoptionlist\fR] [\fB-F\fR i | o | a | s | S] \fB-f\fR \fIfilename\fR
- [\fB-f\fR \fIfilename\fR...]
+ [\fB-f\fR \fIfilename\fR...] [\fIzonename\fR]
.fi
.SH DESCRIPTION
-.sp
.LP
The \fBipf\fR utility is part of a suite of commands associated with the
Solaris IP Filter feature. See \fBipfilter\fR(5).
@@ -34,7 +34,6 @@ matching the order in which they appear when given to \fBipf\fR.
\fB/dev/ipl\fR, and \fB/dev/ipstate\fR. The default permissions of these files
require \fBipf\fR to be run as root for all operations.
.SS "Enabling Solaris IP Filter Feature"
-.sp
.LP
Solaris IP Filter is installed with the Solaris operating system. However,
packet filtering is not enabled by default. Use the following procedure to
@@ -159,7 +158,6 @@ If you reboot your system, the IPfilter configuration is automatically
activated.
.RE
.SH OPTIONS
-.sp
.LP
The following options are supported:
.sp
@@ -257,6 +255,17 @@ packet filter rule lists.
.sp
.ne 2
.na
+\fB\fB-G\fR\fR
+.ad
+.sp .6
+.RS 4n
+Make changes to the Global Zone-controlled ipfilter for the zone given as an
+argument. See the \fBZONES\fR section for more information.
+.RE
+
+.sp
+.ne 2
+.na
\fB\fB-I\fR\fR
.ad
.sp .6
@@ -459,8 +468,25 @@ Zero global statistics held in the kernel for filtering only. This does not
affect fragment or state statistics.
.RE
+.SH ZONES
+.LP
+Each non-global zone has two ipfilter instances: the in-zone ipfilter, which
+can be controlled from both the zone itself and the global zone, and the
+Global Zone-controlled (GZ-controlled) instance, which can only be controlled
+from the Global Zone. The non-global zone is not able to observe or control
+the GZ-controlled ipfilter.
+
+ipf optionally takes a zone name as an argument, which will change the
+ipfilter settings for that zone, rather than the current one. The zonename
+option is only available in the Global Zone. Using it in any other zone will
+return an error. If the \fB-G\fR option is specified with this argument, the
+Global Zone-controlled ipfilter is operated on. If \fB-G\fR is not specified,
+the in-zone ipfilter is operated on. Note that ipf differs from the other
+ipfilter tools in how the zone name is specified. It takes the zone name as the
+last argument, while all of the other tools take the zone name as an argument
+to the \fB-G\fR and \fB-z\fR options.
+
.SH FILES
-.sp
.ne 2
.na
\fB\fB/dev/ipauth\fR\fR
@@ -499,7 +525,6 @@ Contains numerous IP Filter examples.
.RE
.SH ATTRIBUTES
-.sp
.LP
See \fBattributes\fR(5) for descriptions of the following attributes:
.sp
@@ -515,16 +540,14 @@ Interface Stability Committed
.TE
.SH SEE ALSO
-.sp
.LP
\fBipfstat\fR(1M), \fBipmon\fR(1M), \fBipnat\fR(1M), \fBippool\fR(1M),
\fBsvcadm\fR(1M), \fBsvc.ipfd\fR(1M), \fBipf\fR(4), \fBipnat.conf\fR(4),
-\fBippool\fR(4), \fBattributes\fR(5), \fBipfilter\fR(5)
+\fBippool\fR(4), \fBattributes\fR(5), \fBipfilter\fR(5), \fBzones(5)\fR
.sp
.LP
\fI\fR
.SH DIAGNOSTICS
-.sp
.LP
Needs to be run as root for the packet filtering lists to actually be affected
inside the kernel.
diff --git a/usr/src/man/man1m/ipfs.1m b/usr/src/man/man1m/ipfs.1m
index ea2f16c065..38a7f50c7b 100644
--- a/usr/src/man/man1m/ipfs.1m
+++ b/usr/src/man/man1m/ipfs.1m
@@ -2,47 +2,47 @@
.\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed
.\" location.
.\" Portions Copyright (c) 2008, Sun Microsystems Inc. All Rights Reserved.
-.TH IPFS 1M "Apr 3, 2008"
+.\" Portions Copyright (c) 2013, Joyent, Inc. All Rights Reserved.
+.TH IPFS 1M "Oct 30, 2013"
.SH NAME
ipfs \- saves and restores information for NAT and state tables
.SH SYNOPSIS
.LP
.nf
-\fBipfs\fR [\fB-nv\fR] \fB-l\fR
+\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nv\fR] \fB-l\fR
.fi
.LP
.nf
-\fBipfs\fR [\fB-nv\fR] \fB-u\fR
+\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nv\fR] \fB-u\fR
.fi
.LP
.nf
-\fBipfs\fR [\fB-nv\fR] [\fB-d\fR \fIdirname\fR] \fB-R\fR
+\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nv\fR] [\fB-d\fR \fIdirname\fR] \fB-R\fR
.fi
.LP
.nf
-\fBipfs\fR [\fB-nv\fR] [\fB-d\fR \fIdirname\fR] \fB-W\fR
+\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nv\fR] [\fB-d\fR \fIdirname\fR] \fB-W\fR
.fi
.LP
.nf
-\fBipfs\fR [\fB-nNSv\fR] [\fB-f\fR \fIfilename\fR] \fB-r\fR
+\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nNSv\fR] [\fB-f\fR \fIfilename\fR] \fB-r\fR
.fi
.LP
.nf
-\fBipfs\fR [\fB-nNSv\fR] [\fB-f\fR \fIfilename\fR] \fB-w\fR
+\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nNSv\fR] [\fB-f\fR \fIfilename\fR] \fB-w\fR
.fi
.LP
.nf
-\fBipfs\fR [\fB-nNSv\fR] \fB-f\fR \fIfilename\fR \fB-i\fR \fI<if1>\fR,\fI<if2>\fR
+\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nNSv\fR] \fB-f\fR \fIfilename\fR \fB-i\fR \fI<if1>\fR,\fI<if2>\fR
.fi
.SH DESCRIPTION
-.sp
.LP
The \fBipfs\fR utility enables the saving of state information across reboots.
Specifically, the utility allows state information created for NAT entries and
@@ -50,7 +50,6 @@ rules using "keep state" to be locked (modification prevented) and then saved
to disk. Then, after a reboot, that information is restored. The result of this
state-saving is that connections are not interrupted.
.SH OPTIONS
-.sp
.LP
The following options are supported:
.sp
@@ -164,6 +163,30 @@ can be changed with the \fB-d\fR option. The state tables are locked at the
beginning of this operation and unlocked once complete.
.RE
+.sp
+.ne 2
+.na
+\fB\fB-z\fR \fIzonename\fR\fR
+.ad
+.RS 6n
+Operate on the in-zone state information for the specified zone. If neither
+this option nor \fB-G\fR is specified, the current zone is used. This command
+is only available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) for
+more information.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fB-G\fR \fIzonename\fR\fR
+.ad
+.RS 6n
+Operate on the global zone controlled state information for the specified
+zone. If neither this option nor \fB-z\fR is specified, the current zone is
+used. This command is only available in the Global Zone. See \fBZONES\fR in
+\fBipf\fR(1m) for more information.
+.RE
+
.SH FILES
.RS +4
.TP
@@ -196,7 +219,6 @@ beginning of this operation and unlocked once complete.
\fB/dev/ipnat\fR
.RE
.SH ATTRIBUTES
-.sp
.LP
See \fBattributes\fR(5) for descriptions of the following attributes:
.sp
@@ -212,11 +234,10 @@ Interface Stability Committed
.TE
.SH SEE ALSO
-.sp
.LP
-\fBipf\fR(1M), \fBipmon\fR(1M), \fBipnat\fR(1M), \fBattributes\fR(5)
+\fBipf\fR(1M), \fBipmon\fR(1M), \fBipnat\fR(1M), \fBattributes\fR(5),
+\fBzones(5)\fR
.SH DIAGNOSTICS
-.sp
.LP
Arguably, the \fB-W\fR and \fB-R\fR operations should set the locking and,
rather than undo it, restore it to what it was previously.
diff --git a/usr/src/man/man1m/ipfstat.1m b/usr/src/man/man1m/ipfstat.1m
index 212de841a9..ba47f78725 100644
--- a/usr/src/man/man1m/ipfstat.1m
+++ b/usr/src/man/man1m/ipfstat.1m
@@ -2,7 +2,8 @@
.\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed
.\" location.
.\" Portions Copyright (c) 2008, Sun Microsystems Inc. All Rights Reserved.
-.TH IPFSTAT 1M "Apr 3, 2008"
+.\" Portions Copyright (c) 2013, Joyent, Inc. All Rights Reserved.
+.TH IPFSTAT 1M "Oct 30, 2013"
.SH NAME
ipfstat \- reports on packet filter statistics and filter list
.SH SYNOPSIS
@@ -14,11 +15,10 @@ ipfstat \- reports on packet filter statistics and filter list
.LP
.nf
\fBipfstat\fR [\fB-C\fR] [\fB-D\fR \fIaddrport\fR] [\fB-P\fR \fIprotocol\fR] [\fB-S\fR \fIaddrport\fR]
- [\fB-T\fR \fIrefreshtime\fR]
+ [\fB-T\fR \fIrefreshtime\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR]
.fi
.SH DESCRIPTION
-.sp
.LP
The \fBipfstat\fR command is part of a suite of commands associated with the
Solaris IP Filter feature. See \fBipfilter\fR(5).
@@ -132,7 +132,6 @@ Only the first \fIX\fR-5 entries that match the sort and filter criteria are
displayed (where \fIX\fR is the number of rows on the display). There is no way
to see additional entries.
.SH OPTIONS
-.sp
.LP
The following options are supported:
.sp
@@ -351,6 +350,30 @@ shows the process table. States can be sorted in a number of different ways.
Turn verbose mode on. Displays additional debugging information.
.RE
+.sp
+.ne 2
+.na
+\fB\fB-z\fR \fIzonename\fR\fR
+.ad
+.RS 18n
+Report the in-zone statistics for the specified zone. If neither this option
+nor \fB-G\fR is specified, the current zone is used. This command is only
+available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) for more
+information.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fB-G\fR \fIzonename\fR\fR
+.ad
+.RS 18n
+Report the global zone controlled statistics for the specified zone. If
+neither this option nor \fB-z\fR is specified, the current zone is used. This
+command is only available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m)
+for more information.
+.RE
+
.SH FILES
.RS +4
.TP
@@ -377,7 +400,6 @@ Turn verbose mode on. Displays additional debugging information.
\fB/dev/ipstate\fR
.RE
.SH ATTRIBUTES
-.sp
.LP
See \fBattributes\fR(5) for descriptions of the following attributes:
.sp
@@ -393,10 +415,9 @@ Interface Stability Committed
.TE
.SH SEE ALSO
-.sp
.LP
\fBipf\fR(1M), \fBkstat\fR(1M), \fBkstat\fR(3KSTAT), \fBattributes\fR(5),
-\fBipfilter\fR(5)
+\fBipfilter\fR(5), \fBzones(5)\fR
.sp
.LP
\fI\fR
diff --git a/usr/src/man/man1m/ipmon.1m b/usr/src/man/man1m/ipmon.1m
index 2094979915..8873fe41c1 100644
--- a/usr/src/man/man1m/ipmon.1m
+++ b/usr/src/man/man1m/ipmon.1m
@@ -2,18 +2,18 @@
.\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed
.\" location.
.\" Portions Copyright (c) 2008, Sun Microsystems Inc. All Rights Reserved.
-.TH IPMON 1M "Apr 3, 2008"
+.\" Portions Copyright (c) 2013, Joyent, Inc. All Rights Reserved.
+.TH IPMON 1M "Oct 30, 2013"
.SH NAME
ipmon \- monitors /dev/ipl for logged packets
.SH SYNOPSIS
.LP
.nf
\fBipmon\fR [\fB-abDFhnpstvxX\fR] [\fB-N\fR \fIdevice\fR] [ [o] [NSI]] [\fB-O\fR [NSI]]
- [\fB-P\fR \fIpidfile\fR] [\fB-S\fR \fIdevice\fR] [\fB-f\fR \fIdevice\fR] [\fIfilename\fR]
+ [\fB-P\fR \fIpidfile\fR] [\fB-S\fR \fIdevice\fR] [\fB-f\fR \fIdevice\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fIfilename\fR]
.fi
.SH DESCRIPTION
-.sp
.LP
The \fBipmon\fR command is part of a suite of commands associated with the
Solaris IP Filter feature. See \fBipfilter\fR(5).
@@ -102,7 +102,6 @@ always being \fBicmp\fR, the next being the ICMP message and submessage type,
separated by a slash. For example, \fBicmp 3/3\fR for a port unreachable
message.
.SH OPTIONS
-.sp
.LP
The following options are supported:
.sp
@@ -343,6 +342,32 @@ Show the packet data in hex.
Show the log header record data in hex.
.RE
+.sp
+.ne 2
+.na
+\fB\fB-z\fR \fIzonename\fR\fR
+.ad
+.sp .6
+.RS 4n
+Monitor packets the specified zone's in-zone filter. If neither this option
+nor \fB-G\fR is specified, the current zone is used. This command is only
+available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) for more
+information.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fB-G\fR \fIzonename\fR\fR
+.ad
+.sp .6
+.RS 4n
+Monitor packets for the specified zone's global zone controlled filter. If
+neither this option nor \fB-z\fR is specified, the current zone is used. This
+command is only available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m)
+for more information.
+.RE
+
.SH FILES
.RS +4
.TP
@@ -363,7 +388,6 @@ Show the log header record data in hex.
\fB/dev/ipstate\fR
.RE
.SH ATTRIBUTES
-.sp
.LP
See \fBattributes\fR(5) for descriptions of the following attributes:
.sp
@@ -379,15 +403,13 @@ Interface Stability Committed
.TE
.SH SEE ALSO
-.sp
.LP
\fBipf\fR(1M), \fBipfstat\fR(1M), \fBipnat\fR(1M), \fBattributes\fR(5),
-\fBipfilter\fR(5)
+\fBipfilter\fR(5), \fBzones(5)\fR
.sp
.LP
\fI\fR
.SH DIAGNOSTICS
-.sp
.LP
\fBipmon\fR expects data that it reads to be consistent with how it should be
saved and aborts if it fails an assertion which detects an anomaly in the
diff --git a/usr/src/man/man1m/ipnat.1m b/usr/src/man/man1m/ipnat.1m
index 6e36a50e26..e800988bb3 100644
--- a/usr/src/man/man1m/ipnat.1m
+++ b/usr/src/man/man1m/ipnat.1m
@@ -2,17 +2,17 @@
.\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed
.\" location.
.\" Portions Copyright (c) 2008, Sun Microsystems Inc. All Rights Reserved.
-.TH IPNAT 1M "Apr 3, 2008"
+.\" Portions Copyright (c) 2013, Joyent, Inc. All Rights Reserved.
+.TH IPNAT 1M "Oct 30, 2013"
.SH NAME
ipnat \- user interface to the NAT subsystem
.SH SYNOPSIS
.LP
.nf
-\fBipnat\fR [\fB-CdFhlnRrsv\fR] \fB-f\fR \fIfilename\fR
+\fBipnat\fR [\fB-CdFhlnRrsv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] \fB-f\fR \fIfilename\fR
.fi
.SH DESCRIPTION
-.sp
.LP
The \fBipnat\fR utility opens a specified file (treating \fB-\fR as stdin) and
parses it for a set of rules that are to be added or removed from the IP NAT.
@@ -32,7 +32,6 @@ require \fBipnat\fR to be run as root for all operations.
permissions of \fB/dev/ipnat\fR require \fBipnat\fR to be run as root for all
operations.
.SH OPTIONS
-.sp
.LP
The following options are supported:
.sp
@@ -140,10 +139,33 @@ Turn verbose mode on. Displays information relating to rule processing and
active rules/table entries.
.RE
-.SH FILES
.sp
.ne 2
.na
+\fB\fB-z\fR \fIzonename\fR\fR
+.ad
+.RS 15n
+Operate on the in-zone IP NAT for the specified zone. If neither this option
+nor \fB-G\fR is specified, the current zone is used. This command is only
+available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) for more
+information.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fB-G\fR \fIzonename\fR\fR
+.ad
+.RS 15n
+Operate on the global zone controlled IP NAT for the specified zone. If
+neither this option nor \fB-z\fR is specified, the current zone is used. This
+command is only available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m)
+for more information.
+.RE
+
+.SH FILES
+.ne 2
+.na
\fB\fB/dev/ipnat\fR\fR
.ad
.sp .6
@@ -182,7 +204,6 @@ Contains numerous IP Filter examples.
.RE
.SH ATTRIBUTES
-.sp
.LP
See \fBattributes\fR(5) for descriptions of the following attributes:
.sp
@@ -198,6 +219,6 @@ Interface Stability Committed
.TE
.SH SEE ALSO
-.sp
.LP
-\fBipf\fR(1M), \fBipfstat\fR(1M), \fBipnat\fR(4), \fBattributes\fR(5)
+\fBipf\fR(1M), \fBipfstat\fR(1M), \fBipnat\fR(4), \fBattributes\fR(5),
+\fBzones(5)\fR
diff --git a/usr/src/man/man1m/ippool.1m b/usr/src/man/man1m/ippool.1m
index 38e7cc19e6..b32e8355a6 100644
--- a/usr/src/man/man1m/ippool.1m
+++ b/usr/src/man/man1m/ippool.1m
@@ -2,60 +2,60 @@
.\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed
.\" location.
.\" Portions Copyright (c) 2008, Sun Microsystems Inc. All Rights Reserved.
-.TH IPPOOL 1M "Apr 3, 2008"
+.\" Portions Copyright (c) 2012, Joyent, Inc. All Rights Reserved.
+.TH IPPOOL 1M "Nov 26, 2012"
.SH NAME
ippool \- user interface to the IP Filter pools
.SH SYNOPSIS
.LP
.nf
-\fBippool\fR \fB-a\fR [\fB-dnv\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] \fB-i\fR \fIipaddr\fR
+\fBippool\fR \fB-a\fR [\fB-dnv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] \fB-i\fR \fIipaddr\fR
[/\fInetmask\fR]
.fi
.LP
.nf
-\fBippool\fR \fB-A\fR [\fB-dnv\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] [\fB-S\fR \fIseed\fR]
+\fBippool\fR \fB-A\fR [\fB-dnv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] [\fB-S\fR \fIseed\fR]
[\fB-t\fR \fItype\fR]
.fi
.LP
.nf
-\fBippool\fR \fB-f\fR \fIfile\fR [\fB-dnuv\fR]
+\fBippool\fR \fB-f\fR \fIfile\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-dnuv\fR]
.fi
.LP
.nf
-\fBippool\fR \fB-F\fR [\fB-dv\fR] [\fB-o\fR \fIrole\fR] [\fB-t\fR \fItype\fR]
+\fBippool\fR \fB-F\fR [\fB-dv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-o\fR \fIrole\fR] [\fB-t\fR \fItype\fR]
.fi
.LP
.nf
-\fBippool\fR \fB-h\fR [\fB-dv\fR] [\fB-m\fR \fIpoolname\fR] [\fB-t\fR \fItype\fR]
+\fBippool\fR \fB-h\fR [\fB-dv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-m\fR \fIpoolname\fR] [\fB-t\fR \fItype\fR]
.fi
.LP
.nf
-\fBippool\fR \fB-l\fR [\fB-dv\fR] [\fB-m\fR \fIpoolname\fR] [\fB-t\fR \fItype\fR]
+\fBippool\fR \fB-l\fR [\fB-dv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-m\fR \fIpoolname\fR] [\fB-t\fR \fItype\fR]
.fi
.LP
.nf
-\fBippool\fR \fB-r\fR [\fB-dnv\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] \fB-i\fR \fIipaddr\fR
+\fBippool\fR \fB-r\fR [\fB-dnv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] \fB-i\fR \fIipaddr\fR
[/\fInetmask\fR]
.fi
.LP
.nf
-\fBippool\fR \fB-R\fR [\fB-dnv\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] [\fB-t\fR \fItype\fR]
+\fBippool\fR \fB-R\fR [\fB-dnv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] [\fB-t\fR \fItype\fR]
.fi
.LP
.nf
-\fBippool\fR \fB-s\fR [\fB-dtv\fR] [\fB-M\fR \fIcore\fR] [\fB-N\fR \fInamelist\fR]
+\fBippool\fR \fB-s\fR [\fB-dtv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-M\fR \fIcore\fR] [\fB-N\fR \fInamelist\fR]
.fi
.SH DESCRIPTION
-.sp
.LP
The \fBippool\fR utility is used to manage information stored in the IP pools
subsystem of IP Filter software. Configuration file information can be parsed
@@ -76,11 +76,9 @@ and the instance-specific options.
\fB/dev/ipl\fR, and \fB/dev/ipstate\fR. The default permissions of these files
require \fBippool\fR to be run as root for all operations.
.SH OPTIONS
-.sp
.LP
\fBippool\fR supports the option categories described below.
.SS "Global Options"
-.sp
.LP
The following global options are supported:
.sp
@@ -111,8 +109,31 @@ would alter the currently running kernel.
Turn verbose mode on.
.RE
-.SS "Instance-Specific Options"
.sp
+.ne 2
+.na
+\fB\fB-z\fR \fIzonename\fR\fR
+.ad
+.RS 6n
+Manage the specified zone's in-zone IP pools. If neither this option nor
+\fB-G\fR is specified, the current zone is used. This command is only
+available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) for more
+information.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fB-G\fR \fIzonename\fR\fR
+.ad
+.RS 6n
+Manage the specified zone's global zone controlled IP pools. If neither this
+option nor \fB-z\fR is specified, the current zone is used. This command is
+only available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) for more
+information.
+.RE
+
+.SS "Instance-Specific Options"
.LP
The following instance-specific options are supported:
.sp
@@ -198,7 +219,6 @@ Display IP pool statistical information.
.RE
.SS "Other Options"
-.sp
.LP
The following, additional options are supported:
.sp
@@ -282,7 +302,6 @@ kernel, unload it.
.RE
.SH FILES
-.sp
.ne 2
.na
\fB\fB/dev/ippool\fR\fR
@@ -310,7 +329,6 @@ Location of \fBippool\fR startup configuration file.
.RE
.SH ATTRIBUTES
-.sp
.LP
See \fBattributes\fR(5) for descriptions of the following attributes:
.sp
@@ -326,6 +344,6 @@ Interface Stability Committed
.TE
.SH SEE ALSO
-.sp
.LP
-\fBipf\fR(1M), \fBipfstat\fR(1M), \fBippool\fR(4), \fBattributes\fR(5)
+\fBipf\fR(1M), \fBipfstat\fR(1M), \fBippool\fR(4), \fBattributes\fR(5),
+\fBzones(5)\fR
diff --git a/usr/src/man/man5/ipfilter.5 b/usr/src/man/man5/ipfilter.5
index dc9f213a4c..9b995d3c3b 100644
--- a/usr/src/man/man5/ipfilter.5
+++ b/usr/src/man/man5/ipfilter.5
@@ -2,11 +2,11 @@
.\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed
.\" location.
.\" Portions Copyright (c) 2009, Sun Microsystems Inc. All Rights Reserved.
-.TH IPFILTER 5 "May 20, 2009"
+.\" Portions Copyright (c) 2014, Joyent, Inc. All Rights Reserved.
+.TH IPFILTER 5 "Oct 7, 2014"
.SH NAME
ipfilter \- IP packet filtering software
.SH DESCRIPTION
-.sp
.LP
IP Filter is software that provides packet filtering capabilities on a Solaris
system. On a properly setup system, it can be used to build a firewall.
@@ -16,7 +16,6 @@ Solaris IP Filter is installed with the Solaris operating system. However,
packet filtering is not enabled by default. See \fBipf\fR(1M) for a procedure
to enable and activate the IP Filter feature.
.SH HOST-BASED FIREWALL
-.sp
.LP
To simplify IP Filter configuration management, a firewall framework is created
to allow users to configure IP Filter by expressing firewall policy at system
@@ -34,14 +33,13 @@ Users can still specify their own ipf rule file if they choose not to take
advantage of the framework. See \fBipf\fR(1M) and \fBipf\fR(4).
.RE
.SS "Model"
-.sp
.LP
This section describes the host-based firewall framework. See svc.ipfd(1M) for
details on how to configure firewall policies.
.sp
.LP
-A three-layer approach with different precedence levels helps the user achieve
-the desired behaviors.
+In a given zone, a three-layer approach with different precedence levels helps
+the user achieve the desired behaviors.
.sp
.ne 2
.na
@@ -127,7 +125,6 @@ Deny all incoming traffic but allow from specified source(s).
.RE
.SS "Layers in Detail"
-.sp
.LP
The first system-wide layer, Global Default, defines a firewall policy that
applies to \fBany\fR incoming traffic, for example, allowing or blocking all
@@ -157,7 +154,6 @@ overrides policies in the other layers, specifically overriding the needs of
network services. The example is when it is desirable to block known malicious
source(s) regardless of services' policies.
.SS "User Interaction"
-.sp
.LP
This framework leverages IP Filter functionality and is active only when
\fBsvc:/network/ipfilter\fR is enabled and inactive when \fBnetwork/ipfilter\fR
@@ -207,10 +203,95 @@ network service
.el o
changes to system-wide or per-service firewall policy results in an update to
the system's firewall rules
-.RE
-.SH ATTRIBUTES
+
+.SS "In-Zone and Global Zone Controlled firewalls"
+.LP
+Each non-global zone in the system can potentially have two firewalls
+configured: the in-zone firewall and the Global Zone controlled (GZ-controlled)
+firewall. The in-zone firewall can be controlled and observed inside the zone
+using the framework detailed above, or from the Global Zone. The GZ-controlled
+firewall can only be controlled and observed from the Global Zone. The
+GZ-controlled firewall is always "outermost" with respect to the zone.
+.sp
+.LP
+For inbound traffic (from an external source to the zone), the traffic flow looks
+like the following diagram. Traffic blocked by the GZ-controlled firewall will
+not be processed by the in-zone firewall.
+.sp
+.in +2
+.nf
+ External Source
+ |
+ |
+GZ-controlled Firewall
+ |
+ |
+ In-Zone Firewall
+ |
+ |
+ Zone
+.fi
+.in -2
+.sp
+.LP
+For outbound traffic (from the zone to an external destination), the traffic
+flow looks like the following diagram. Traffic blocked by the in-zone firewall
+will not be processed by the GZ-controlled firewall.
+.sp
+.in +2
+.nf
+ Zone
+ |
+ |
+ In-Zone Firewall
+ |
+ |
+GZ-controlled Firewall
+ |
+ |
+ External Destination
+.fi
+.in -2
+.sp
+.LP
+Either of the in-Zone or GZ-controlled firewalls can be enabled, or both at the
+same time.
+.sp
+.LP
+The Global Zone does not have a GZ-controlled firewall, only an
+in-zone firewall. For inbound traffic (from an external source to the global
+zone), the traffic flow therefore looks like the following diagram.
+.sp
+.in +2
+.nf
+ External Source
+ |
+ |
+ In-Zone Firewall
+ |
+ |
+ Zone
+.fi
+.in -2
.sp
.LP
+For outbound traffic (from the global zone to an external destination), the
+traffic flow looks like the following diagram.
+.sp
+.in +2
+.nf
+ Zone
+ |
+ |
+ In-Zone Firewall
+ |
+ |
+ External Destination
+.fi
+.in -2
+
+.SH ATTRIBUTES
+.LP
See \fBattributes\fR(5) for a description of the following attributes:
.sp
@@ -225,7 +306,6 @@ Interface Stability Committed
.TE
.SH SEE ALSO
-.sp
.LP
\fBsvcs\fR(1), \fBipf\fR(1M), \fBipnat\fR(1M), \fBsvcadm\fR(1M),
\fBsvc.ipfd\fR(1M), \fBipf\fR(4), \fBipnat\fR(4), \fBattributes\fR(5),
@@ -234,7 +314,6 @@ Interface Stability Committed
.LP
\fISystem Administration Guide: IP Services\fR
.SH NOTES
-.sp
.LP
The \fBipfilter\fR service is managed by the service management facility,
\fBsmf\fR(5), under the service identifier:
diff --git a/usr/src/uts/common/inet/ipf/fil.c b/usr/src/uts/common/inet/ipf/fil.c
index 3955d881e8..67a82d2f68 100644
--- a/usr/src/uts/common/inet/ipf/fil.c
+++ b/usr/src/uts/common/inet/ipf/fil.c
@@ -4,6 +4,8 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
*/
#if defined(KERNEL) || defined(_KERNEL)
@@ -134,6 +136,9 @@ struct file;
# endif
#endif
#include "netinet/ipl.h"
+#if defined(_KERNEL)
+#include <sys/sunddi.h>
+#endif
/* END OF INCLUDES */
#if !defined(lint)
@@ -5696,6 +5701,54 @@ static int fr_objbytes[NUM_OBJ_TYPES][2] = {
/* ------------------------------------------------------------------------ */
+/* Function: fr_getzoneid */
+/* Returns: int - 0 = success, else failure */
+/* Parameters: idsp(I) - pointer to ipf_devstate_t */
+/* data(I) - pointer to ioctl data */
+/* */
+/* Set the zone ID in idsp based on the zone name in ipfzoneobj. Further */
+/* ioctls will act on the IPF stack for that zone ID. */
+/* ------------------------------------------------------------------------ */
+#if defined(_KERNEL)
+int fr_setzoneid(idsp, data)
+ipf_devstate_t *idsp;
+void *data;
+{
+ int error = 0;
+ ipfzoneobj_t ipfzo;
+ zone_t *zone;
+
+ error = BCOPYIN(data, &ipfzo, sizeof(ipfzo));
+ if (error != 0)
+ return EFAULT;
+
+ if (memchr(ipfzo.ipfz_zonename, '\0', ZONENAME_MAX) == NULL)
+ return EFAULT;
+
+ /*
+ * The global zone doesn't have a GZ-controlled stack, so no
+ * sense in going any further
+ */
+ if (strcmp(ipfzo.ipfz_zonename, "global") == 0)
+ return ENODEV;
+
+ if ((zone = zone_find_by_name(ipfzo.ipfz_zonename)) == NULL)
+ return ENODEV;
+
+ /*
+ * Store the zone ID that to control, and whether it's the
+ * GZ-controlled stack that's wanted
+ */
+ idsp->ipfs_zoneid = zone->zone_id;
+ idsp->ipfs_gz = (ipfzo.ipfz_gz == 1) ? B_TRUE : B_FALSE;
+ zone_rele(zone);
+
+ return error;
+}
+#endif
+
+
+/* ------------------------------------------------------------------------ */
/* Function: fr_inobj */
/* Returns: int - 0 = success, else failure */
/* Parameters: data(I) - pointer to ioctl data */
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 c6738164ee..20dc18b588 100644
--- a/usr/src/uts/common/inet/ipf/ip_fil_solaris.c
+++ b/usr/src/uts/common/inet/ipf/ip_fil_solaris.c
@@ -4,6 +4,8 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#if !defined(lint)
@@ -101,6 +103,54 @@ u_long *ip_forwarding = NULL;
#endif
#endif
+vmem_t *ipf_minor; /* minor number arena */
+void *ipf_state; /* DDI state */
+
+/*
+ * GZ-controlled and per-zone stacks:
+ *
+ * For each non-global zone, we create two ipf stacks: the per-zone stack and
+ * the GZ-controlled stack. The per-zone stack can be controlled and observed
+ * from inside the zone or from the global zone. The GZ-controlled stack can
+ * only be controlled and observed from the global zone (though the rules
+ * still only affect that non-global zone).
+ *
+ * The two hooks are always arranged so that the GZ-controlled stack is always
+ * "outermost" with respect to the zone. The traffic flow then looks like
+ * this:
+ *
+ * Inbound:
+ *
+ * nic ---> [ GZ-controlled rules ] ---> [ per-zone rules ] ---> zone
+ *
+ * Outbound:
+ *
+ * nic <--- [ GZ-controlled rules ] <--- [ per-zone rules ] <--- zone
+ */
+
+/* IPv4 hook names */
+char *hook4_nicevents = "ipfilter_hook4_nicevents";
+char *hook4_nicevents_gz = "ipfilter_hook4_nicevents_gz";
+char *hook4_in = "ipfilter_hook4_in";
+char *hook4_in_gz = "ipfilter_hook4_in_gz";
+char *hook4_out = "ipfilter_hook4_out";
+char *hook4_out_gz = "ipfilter_hook4_out_gz";
+char *hook4_loop_in = "ipfilter_hook4_loop_in";
+char *hook4_loop_in_gz = "ipfilter_hook4_loop_in_gz";
+char *hook4_loop_out = "ipfilter_hook4_loop_out";
+char *hook4_loop_out_gz = "ipfilter_hook4_loop_out_gz";
+
+/* IPv6 hook names */
+char *hook6_nicevents = "ipfilter_hook6_nicevents";
+char *hook6_nicevents_gz = "ipfilter_hook6_nicevents_gz";
+char *hook6_in = "ipfilter_hook6_in";
+char *hook6_in_gz = "ipfilter_hook6_in_gz";
+char *hook6_out = "ipfilter_hook6_out";
+char *hook6_out_gz = "ipfilter_hook6_out_gz";
+char *hook6_loop_in = "ipfilter_hook6_loop_in";
+char *hook6_loop_in_gz = "ipfilter_hook6_loop_in_gz";
+char *hook6_loop_out = "ipfilter_hook6_loop_out";
+char *hook6_loop_out_gz = "ipfilter_hook6_loop_out_gz";
/* ------------------------------------------------------------------------ */
/* Function: ipldetach */
@@ -117,7 +167,7 @@ int ipldetach(ifs)
ipf_stack_t *ifs;
{
- ASSERT(rw_read_locked(&ifs->ifs_ipf_global.ipf_lk) == 0);
+ ASSERT(RW_WRITE_HELD(&ifs->ifs_ipf_global.ipf_lk));
#if SOLARIS2 < 10
@@ -244,7 +294,7 @@ ipf_stack_t *ifs;
cmn_err(CE_CONT, "iplattach()\n");
#endif
- ASSERT(rw_read_locked(&ifs->ifs_ipf_global.ipf_lk) == 0);
+ ASSERT(RW_WRITE_HELD(&ifs->ifs_ipf_global.ipf_lk));
ifs->ifs_fr_flags = IPF_LOGGING;
#ifdef _KERNEL
ifs->ifs_fr_update_ipid = 0;
@@ -269,16 +319,39 @@ ipf_stack_t *ifs;
if (fr_initialise(ifs) < 0)
return -1;
- HOOK_INIT(ifs->ifs_ipfhook4_nicevents, ipf_nic_event_v4,
- "ipfilter_hook4_nicevents", ifs);
- HOOK_INIT(ifs->ifs_ipfhook4_in, ipf_hook4_in,
- "ipfilter_hook4_in", ifs);
- HOOK_INIT(ifs->ifs_ipfhook4_out, ipf_hook4_out,
- "ipfilter_hook4_out", ifs);
- HOOK_INIT(ifs->ifs_ipfhook4_loop_in, ipf_hook4_loop_in,
- "ipfilter_hook4_loop_in", ifs);
- HOOK_INIT(ifs->ifs_ipfhook4_loop_out, ipf_hook4_loop_out,
- "ipfilter_hook4_loop_out", ifs);
+ /*
+ * For incoming packets, we want the GZ-controlled hooks to run before
+ * the per-zone hooks, regardless of what order they're are installed.
+ * See the "GZ-controlled and per-zone stacks" comment block at the top
+ * of this file.
+ */
+#define HOOK_INIT_GZ_BEFORE(x, fn, n, gzn, a) \
+ HOOK_INIT(x, fn, ifs->ifs_gz_controlled ? gzn : n, ifs); \
+ (x)->h_hint = ifs->ifs_gz_controlled ? HH_BEFORE : HH_AFTER; \
+ (x)->h_hintvalue = (uintptr_t) (ifs->ifs_gz_controlled ? n : gzn);
+
+ HOOK_INIT_GZ_BEFORE(ifs->ifs_ipfhook4_nicevents, ipf_nic_event_v4,
+ hook4_nicevents, hook4_nicevents_gz, ifs);
+ HOOK_INIT_GZ_BEFORE(ifs->ifs_ipfhook4_in, ipf_hook4_in,
+ hook4_in, hook4_in_gz, ifs);
+ HOOK_INIT_GZ_BEFORE(ifs->ifs_ipfhook4_loop_in, ipf_hook4_loop_in,
+ hook4_loop_in, hook4_loop_in_gz, ifs);
+
+ /*
+ * For outgoing packets, we want the GZ-controlled hooks to run after
+ * the per-zone hooks, regardless of what order they're are installed.
+ * See the "GZ-controlled and per-zone stacks" comment block at the top
+ * of this file.
+ */
+#define HOOK_INIT_GZ_AFTER(x, fn, n, gzn, a) \
+ HOOK_INIT(x, fn, ifs->ifs_gz_controlled ? gzn : n, ifs); \
+ (x)->h_hint = ifs->ifs_gz_controlled ? HH_AFTER : HH_BEFORE; \
+ (x)->h_hintvalue = (uintptr_t) (ifs->ifs_gz_controlled ? n : gzn);
+
+ HOOK_INIT_GZ_AFTER(ifs->ifs_ipfhook4_out, ipf_hook4_out,
+ hook4_out, hook4_out_gz, ifs);
+ HOOK_INIT_GZ_AFTER(ifs->ifs_ipfhook4_loop_out, ipf_hook4_loop_out,
+ hook4_loop_out, hook4_loop_out_gz, ifs);
/*
* If we hold this lock over all of the net_hook_register calls, we
@@ -323,6 +396,7 @@ ipf_stack_t *ifs;
if (!ifs->ifs_hook4_loopback_out)
goto hookup_failed;
}
+
/*
* Add IPv6 hooks
*/
@@ -330,16 +404,16 @@ ipf_stack_t *ifs;
if (ifs->ifs_ipf_ipv6 == NULL)
goto hookup_failed;
- HOOK_INIT(ifs->ifs_ipfhook6_nicevents, ipf_nic_event_v6,
- "ipfilter_hook6_nicevents", ifs);
- HOOK_INIT(ifs->ifs_ipfhook6_in, ipf_hook6_in,
- "ipfilter_hook6_in", ifs);
- HOOK_INIT(ifs->ifs_ipfhook6_out, ipf_hook6_out,
- "ipfilter_hook6_out", ifs);
- HOOK_INIT(ifs->ifs_ipfhook6_loop_in, ipf_hook6_loop_in,
- "ipfilter_hook6_loop_in", ifs);
- HOOK_INIT(ifs->ifs_ipfhook6_loop_out, ipf_hook6_loop_out,
- "ipfilter_hook6_loop_out", ifs);
+ HOOK_INIT_GZ_BEFORE(ifs->ifs_ipfhook6_nicevents, ipf_nic_event_v6,
+ hook6_nicevents, hook6_nicevents_gz, ifs);
+ HOOK_INIT_GZ_BEFORE(ifs->ifs_ipfhook6_in, ipf_hook6_in,
+ hook6_in, hook6_in_gz, ifs);
+ HOOK_INIT_GZ_BEFORE(ifs->ifs_ipfhook6_loop_in, ipf_hook6_loop_in,
+ hook6_loop_in, hook6_loop_in_gz, ifs);
+ HOOK_INIT_GZ_AFTER(ifs->ifs_ipfhook6_out, ipf_hook6_out,
+ hook6_out, hook6_out_gz, ifs);
+ HOOK_INIT_GZ_AFTER(ifs->ifs_ipfhook6_loop_out, ipf_hook6_loop_out,
+ hook6_loop_out, hook6_loop_out_gz, ifs);
ifs->ifs_hook6_nic_events = (net_hook_register(ifs->ifs_ipf_ipv6,
NH_NIC_EVENTS, ifs->ifs_ipfhook6_nicevents) == 0);
@@ -519,35 +593,47 @@ int *rp;
minor_t unit;
u_int enable;
ipf_stack_t *ifs;
+ zoneid_t zid;
+ ipf_devstate_t *isp;
#ifdef IPFDEBUG
cmn_err(CE_CONT, "iplioctl(%x,%x,%x,%d,%x,%d)\n",
dev, cmd, data, mode, cp, rp);
#endif
unit = getminor(dev);
- if (IPL_LOGMAX < unit)
+
+ isp = ddi_get_soft_state(ipf_state, unit);
+ if (isp == NULL)
return ENXIO;
+ unit = isp->ipfs_minor;
+
+ zid = crgetzoneid(cp);
+ if (cmd == SIOCIPFZONESET) {
+ if (zid == GLOBAL_ZONEID)
+ return fr_setzoneid(isp, (caddr_t) data);
+ return EACCES;
+ }
/*
- * As we're calling ipf_find_stack in user space, from a given zone
- * to find the stack pointer for this zone, there is no need to have
- * a hold/refence count here.
+ * ipf_find_stack returns with a read lock on ifs_ipf_global
*/
- ifs = ipf_find_stack(crgetzoneid(cp));
- ASSERT(ifs != NULL);
+ ifs = ipf_find_stack(zid, isp);
+ if (ifs == NULL)
+ return ENXIO;
if (ifs->ifs_fr_running <= 0) {
if (unit != IPL_LOGIPF) {
+ RWLOCK_EXIT(&ifs->ifs_ipf_global);
return EIO;
}
if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET &&
cmd != SIOCIPFSET && cmd != SIOCFRENB &&
cmd != SIOCGETFS && cmd != SIOCGETFF) {
+ RWLOCK_EXIT(&ifs->ifs_ipf_global);
return EIO;
}
}
- READ_ENTER(&ifs->ifs_ipf_global);
if (ifs->ifs_fr_enable_active != 0) {
RWLOCK_EXIT(&ifs->ifs_ipf_global);
return EBUSY;
@@ -848,7 +934,9 @@ dev_t *devp;
int flags, otype;
cred_t *cred;
{
+ ipf_devstate_t *isp;
minor_t min = getminor(*devp);
+ minor_t minor;
#ifdef IPFDEBUG
cmn_err(CE_CONT, "iplopen(%x,%x,%x,%x)\n", devp, flags, otype, cred);
@@ -856,8 +944,25 @@ cred_t *cred;
if (!(otype & OTYP_CHR))
return ENXIO;
- min = (IPL_LOGMAX < min) ? ENXIO : 0;
- return min;
+ if (IPL_LOGMAX < min)
+ return ENXIO;
+
+ minor = (minor_t)(uintptr_t)vmem_alloc(ipf_minor, 1,
+ VM_BESTFIT | VM_SLEEP);
+
+ if (ddi_soft_state_zalloc(ipf_state, minor) != 0) {
+ vmem_free(ipf_minor, (void *)(uintptr_t)minor, 1);
+ return ENXIO;
+ }
+
+ *devp = makedevice(getmajor(*devp), minor);
+ isp = ddi_get_soft_state(ipf_state, minor);
+ VERIFY(isp != NULL);
+
+ isp->ipfs_minor = min;
+ isp->ipfs_zoneid = IPFS_ZONE_UNSET;
+
+ return 0;
}
@@ -873,8 +978,13 @@ cred_t *cred;
cmn_err(CE_CONT, "iplclose(%x,%x,%x,%x)\n", dev, flags, otype, cred);
#endif
- min = (IPL_LOGMAX < min) ? ENXIO : 0;
- return min;
+ if (IPL_LOGMAX < min)
+ return ENXIO;
+
+ ddi_soft_state_free(ipf_state, min);
+ vmem_free(ipf_minor, (void *)(uintptr_t)min, 1);
+
+ return 0;
}
#ifdef IPFILTER_LOG
@@ -892,30 +1002,41 @@ cred_t *cp;
{
ipf_stack_t *ifs;
int ret;
+ minor_t unit;
+ ipf_devstate_t *isp;
+
+ unit = getminor(dev);
+ isp = ddi_get_soft_state(ipf_state, unit);
+ if (isp == NULL)
+ return ENXIO;
+ unit = isp->ipfs_minor;
+
/*
- * As we're calling ipf_find_stack in user space, from a given zone
- * to find the stack pointer for this zone, there is no need to have
- * a hold/refence count here.
+ * ipf_find_stack returns with a read lock on ifs_ipf_global
*/
- ifs = ipf_find_stack(crgetzoneid(cp));
- ASSERT(ifs != NULL);
+ ifs = ipf_find_stack(crgetzoneid(cp), isp);
+ if (ifs == NULL)
+ return ENXIO;
# ifdef IPFDEBUG
cmn_err(CE_CONT, "iplread(%x,%x,%x)\n", dev, uio, cp);
# endif
if (ifs->ifs_fr_running < 1) {
+ RWLOCK_EXIT(&ifs->ifs_ipf_global);
return EIO;
}
# ifdef IPFILTER_SYNC
- if (getminor(dev) == IPL_LOGSYNC) {
+ if (unit == IPL_LOGSYNC) {
+ RWLOCK_EXIT(&ifs->ifs_ipf_global);
return ipfsync_read(uio);
}
# endif
- ret = ipflog_read(getminor(dev), uio, ifs);
+ ret = ipflog_read(unit, uio, ifs);
+ RWLOCK_EXIT(&ifs->ifs_ipf_global);
return ret;
}
#endif /* IPFILTER_LOG */
@@ -933,30 +1054,41 @@ register struct uio *uio;
cred_t *cp;
{
ipf_stack_t *ifs;
+ minor_t unit;
+ ipf_devstate_t *isp;
+
+ unit = getminor(dev);
+ isp = ddi_get_soft_state(ipf_state, unit);
+ if (isp == NULL)
+ return ENXIO;
+ unit = isp->ipfs_minor;
/*
- * As we're calling ipf_find_stack in user space, from a given zone
- * to find the stack pointer for this zone, there is no need to have
- * a hold/refence count here.
+ * ipf_find_stack returns with a read lock on ifs_ipf_global
*/
- ifs = ipf_find_stack(crgetzoneid(cp));
- ASSERT(ifs != NULL);
+ ifs = ipf_find_stack(crgetzoneid(cp), isp);
+ if (ifs == NULL)
+ return ENXIO;
#ifdef IPFDEBUG
cmn_err(CE_CONT, "iplwrite(%x,%x,%x)\n", dev, uio, cp);
#endif
if (ifs->ifs_fr_running < 1) {
+ RWLOCK_EXIT(&ifs->ifs_ipf_global);
return EIO;
}
#ifdef IPFILTER_SYNC
- if (getminor(dev) == IPL_LOGSYNC)
+ if (getminor(dev) == IPL_LOGSYNC) {
+ RWLOCK_EXIT(&ifs->ifs_ipf_global);
return ipfsync_write(uio);
+ }
#endif /* IPFILTER_SYNC */
dev = dev; /* LINT */
uio = uio; /* LINT */
cp = cp; /* LINT */
+ RWLOCK_EXIT(&ifs->ifs_ipf_global);
return ENXIO;
}
@@ -1998,7 +2130,6 @@ int ipf_hook6(hook_data_t info, int out, int loopback, void *arg)
fw->hpe_mb = qpi.qpi_m;
fw->hpe_hdr = qpi.qpi_data;
return rval;
-
}
diff --git a/usr/src/uts/common/inet/ipf/ip_log.c b/usr/src/uts/common/inet/ipf/ip_log.c
index 1fe54f3a07..d60a666b2d 100644
--- a/usr/src/uts/common/inet/ipf/ip_log.c
+++ b/usr/src/uts/common/inet/ipf/ip_log.c
@@ -7,6 +7,8 @@
*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
*/
#include <sys/param.h>
@@ -572,10 +574,18 @@ ipf_stack_t *ifs;
while (ifs->ifs_iplt[unit] == NULL) {
# if SOLARIS && defined(_KERNEL)
+ /*
+ * Prevent a deadlock with ipldetach() - see the "ipfilter
+ * kernel module mutexes and locking" comment block in solaris.c
+ * for details.
+ */
+ RWLOCK_EXIT(&ifs->ifs_ipf_global);
if (!cv_wait_sig(&ifs->ifs_iplwait, &ifs->ifs_ipl_mutex.ipf_lk)) {
+ READ_ENTER(&ifs->ifs_ipf_global);
MUTEX_EXIT(&ifs->ifs_ipl_mutex);
return EINTR;
}
+ READ_ENTER(&ifs->ifs_ipf_global);
# else
# if defined(__hpux) && defined(_KERNEL)
lock_t *l;
diff --git a/usr/src/uts/common/inet/ipf/ip_state.c b/usr/src/uts/common/inet/ipf/ip_state.c
index adf9ff9382..c1fe642d00 100644
--- a/usr/src/uts/common/inet/ipf/ip_state.c
+++ b/usr/src/uts/common/inet/ipf/ip_state.c
@@ -4,6 +4,8 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
*/
#if defined(KERNEL) || defined(_KERNEL)
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 0a2d6431d8..479a8044f4 100644
--- a/usr/src/uts/common/inet/ipf/netinet/ip_fil.h
+++ b/usr/src/uts/common/inet/ipf/netinet/ip_fil.h
@@ -7,12 +7,15 @@
* $Id: ip_fil.h,v 2.170.2.22 2005/07/16 05:55:35 darrenr Exp $
*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
*/
#ifndef __IP_FIL_H__
#define __IP_FIL_H__
#include "netinet/ip_compat.h"
+#include <sys/zone.h>
#ifndef SOLARIS
# define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
@@ -106,6 +109,7 @@
#define SIOCADDFR SIOCADAFR
#define SIOCDELFR SIOCRMAFR
#define SIOCINSFR SIOCINAFR
+# define SIOCIPFZONESET _IOWR('r', 97, struct ipfzoneobj)
/*
* What type of table is getting flushed?
@@ -1165,6 +1169,26 @@ typedef struct ipfobj {
u_char ipfo_xxxpad[32]; /* reserved for future use */
} ipfobj_t;
+/*
+ * ioctl struct for setting what zone further ioctls will act on. ipfz_gz is a
+ * boolean: set it to 1 to operate on the GZ-controlled stack.
+ */
+typedef struct ipfzoneobj {
+ u_32_t ipfz_gz; /* GZ stack boolean */
+ char ipfz_zonename[ZONENAME_MAX]; /* zone to act on */
+} ipfzoneobj_t;
+
+#if defined(_KERNEL)
+/* Set ipfs_zoneid to this if no zone has been set: */
+#define IPFS_ZONE_UNSET -2
+
+typedef struct ipf_devstate {
+ zoneid_t ipfs_zoneid;
+ minor_t ipfs_minor;
+ boolean_t ipfs_gz;
+} ipf_devstate_t;
+#endif
+
#define IPFOBJ_FRENTRY 0 /* struct frentry */
#define IPFOBJ_IPFSTAT 1 /* struct friostat */
#define IPFOBJ_IPFINFO 2 /* struct fr_info */
@@ -1352,7 +1376,6 @@ extern void ipfilterattach __P((int));
extern int ipl_enable __P((void));
extern int ipl_disable __P((void));
# ifdef MENTAT
-extern ipf_stack_t *ipf_find_stack(const zoneid_t zone);
extern int fr_check __P((struct ip *, int, void *, int, void *,
mblk_t **, ipf_stack_t *));
# if SOLARIS
@@ -1365,6 +1388,7 @@ extern int iplioctl __P((dev_t, int, int *, int, cred_t *, int *));
extern int fr_make_rst __P((fr_info_t *));
extern int fr_make_icmp __P((fr_info_t *));
extern void fr_calc_chksum __P((fr_info_t *, mb_t *));
+extern ipf_stack_t *ipf_find_stack(const zoneid_t, ipf_devstate_t *);
# endif
extern int iplopen __P((dev_t *, int, int, cred_t *));
extern int iplclose __P((dev_t, int, int, cred_t *));
@@ -1576,6 +1600,10 @@ extern int ipf_earlydrop __P((int, ipftq_t *, int, ipf_stack_t *));
extern u_32_t ipf_random __P((void));
#endif
+#if defined(_KERNEL)
+extern int fr_setzoneid __P((ipf_devstate_t *, void *));
+#endif
+
extern char ipfilter_version[];
#ifdef USE_INET6
extern int icmptoicmp6types[ICMP_MAXTYPE+1];
diff --git a/usr/src/uts/common/inet/ipf/netinet/ipf_stack.h b/usr/src/uts/common/inet/ipf/netinet/ipf_stack.h
index 75703994a5..a239f1c1ca 100644
--- a/usr/src/uts/common/inet/ipf/netinet/ipf_stack.h
+++ b/usr/src/uts/common/inet/ipf/netinet/ipf_stack.h
@@ -5,6 +5,8 @@
*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2014 Joyent, Inc. All rights reserved.
*/
#ifndef __IPF_STACK_H__
@@ -41,8 +43,10 @@
struct ipf_stack {
struct ipf_stack *ifs_next;
struct ipf_stack **ifs_pnext;
+ struct ipf_stack *ifs_gz_cont_ifs;
netid_t ifs_netid;
zoneid_t ifs_zone;
+ boolean_t ifs_gz_controlled;
/* ipf module */
fr_info_t ifs_frcache[2][8];
diff --git a/usr/src/uts/common/inet/ipf/solaris.c b/usr/src/uts/common/inet/ipf/solaris.c
index 1a1d94def5..c541f4dddc 100644
--- a/usr/src/uts/common/inet/ipf/solaris.c
+++ b/usr/src/uts/common/inet/ipf/solaris.c
@@ -5,6 +5,50 @@
*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * ipfilter kernel module mutexes and locking:
+ *
+ * Enabling ipfilter creates a per-netstack ipf_stack_t object that is
+ * stored in the ipf_stacks list, which is protected by ipf_stack_lock.
+ * ipf_stack_t objects are accessed in three contexts:
+ *
+ * 1) administering that filter (eg: ioctls handled with iplioctl())
+ * 2) reading log data (eg: iplread() / iplwrite())
+ * 3) filtering packets (eg: ipf_hook4_* and ipf_hook6_* pfhooks
+ * functions)
+ *
+ * Each ipf_stack_t has a RW lock, ifs_ipf_global, protecting access to the
+ * whole structure. The structure also has locks protecting the various
+ * data structures used for filtering. The following guidelines should be
+ * followed for ipf_stack_t locks:
+ *
+ * - ipf_stack_lock must be held when accessing the ipf_stacks list
+ * - ipf_stack_lock should be held before acquiring ifs_ipf_global for
+ * a stack (the exception to this is ipf_stack_destroy(), which removes
+ * the ipf_stack_t from the list, then drops ipf_stack_lock before
+ * acquiring ifs_ipf_global)
+ * - ifs_ipf_global must be held when accessing an ipf_stack_t in that list:
+ * - The write lock is held only during stack creation / destruction
+ * - The read lock should be held for all other accesses
+ * - To alter the filtering data in the administrative context, one must:
+ * - acquire the read lock for ifs_ipf_global
+ * - then acquire the write lock for the data in question
+ * - In the filtering path, the read lock needs to be held for each type of
+ * filtering data used
+ * - ifs_ipf_global does not need to be held in the filtering path:
+ * - The filtering hooks don't need to modify the stack itself
+ * - The ipf_stack_t will not be destroyed until the hooks are unregistered.
+ * This requires a write lock on the hook, ensuring that no active hooks
+ * (eg: the filtering path) are running, and that the hooks won't be run
+ * afterward.
+ *
+ * Note that there is a deadlock possible when calling net_hook_register()
+ * or net_hook_unregister() with ifs_ipf_global held: see the comments in
+ * iplattach() and ipldetach() for details.
*/
#include <sys/systm.h>
@@ -73,7 +117,8 @@ static int ipf_property_g_update __P((dev_info_t *));
static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME,
IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME,
IPLOOKUP_NAME, NULL };
-
+extern void *ipf_state; /* DDI state */
+extern vmem_t *ipf_minor; /* minor number arena */
static struct cb_ops ipf_cb_ops = {
iplopen,
@@ -221,10 +266,11 @@ static const filter_kstats_t ipf_kstat_tmp = {
static int ipf_kstat_update(kstat_t *ksp, int rwflag);
static void
-ipf_kstat_init(ipf_stack_t *ifs)
+ipf_kstat_init(ipf_stack_t *ifs, boolean_t from_gz)
{
- ifs->ifs_kstatp[0] = net_kstat_create(ifs->ifs_netid, "ipf", 0,
- "inbound", "net", KSTAT_TYPE_NAMED,
+ ifs->ifs_kstatp[0] = net_kstat_create(ifs->ifs_netid,
+ (from_gz ? "ipf_gz" : "ipf"),
+ 0, "inbound", "net", KSTAT_TYPE_NAMED,
sizeof (filter_kstats_t) / sizeof (kstat_named_t), 0);
if (ifs->ifs_kstatp[0] != NULL) {
bcopy(&ipf_kstat_tmp, ifs->ifs_kstatp[0]->ks_data,
@@ -234,8 +280,9 @@ ipf_kstat_init(ipf_stack_t *ifs)
kstat_install(ifs->ifs_kstatp[0]);
}
- ifs->ifs_kstatp[1] = net_kstat_create(ifs->ifs_netid, "ipf", 0,
- "outbound", "net", KSTAT_TYPE_NAMED,
+ ifs->ifs_kstatp[1] = net_kstat_create(ifs->ifs_netid,
+ (from_gz ? "ipf_gz" : "ipf"),
+ 0, "outbound", "net", KSTAT_TYPE_NAMED,
sizeof (filter_kstats_t) / sizeof (kstat_named_t), 0);
if (ifs->ifs_kstatp[1] != NULL) {
bcopy(&ipf_kstat_tmp, ifs->ifs_kstatp[1]->ks_data,
@@ -369,12 +416,14 @@ dev_info_t *dip;
* Initialize things for IPF for each stack instance
*/
static void *
-ipf_stack_create(const netid_t id)
+ipf_stack_create_one(const netid_t id, const zoneid_t zid, boolean_t from_gz,
+ ipf_stack_t *ifs_gz)
{
ipf_stack_t *ifs;
#ifdef IPFDEBUG
- cmn_err(CE_NOTE, "IP Filter:stack_create id=%d", id);
+ cmn_err(CE_NOTE, "IP Filter:stack_create_one id=%d global=%d", id,
+ global);
#endif
ifs = (ipf_stack_t *)kmem_alloc(sizeof (*ifs), KM_SLEEP);
@@ -398,8 +447,11 @@ ipf_stack_create(const netid_t id)
RWLOCK_INIT(&ifs->ifs_ipf_mutex, "ipf filter rwlock");
RWLOCK_INIT(&ifs->ifs_ipf_frcache, "ipf cache rwlock");
ifs->ifs_netid = id;
- ifs->ifs_zone = net_getzoneidbynetid(id);
- ipf_kstat_init(ifs);
+ ifs->ifs_zone = zid;
+ ifs->ifs_gz_controlled = from_gz;
+ ifs->ifs_gz_cont_ifs = ifs_gz;
+
+ ipf_kstat_init(ifs, from_gz);
#ifdef IPFDEBUG
cmn_err(CE_CONT, "IP Filter:stack_create zone=%d", ifs->ifs_zone);
@@ -427,31 +479,84 @@ ipf_stack_create(const netid_t id)
return (ifs);
}
+static void *
+ipf_stack_create(const netid_t id)
+{
+ ipf_stack_t *ifs = NULL;
+ zoneid_t zid = net_getzoneidbynetid(id);
+
+ /*
+ * Create two ipfilter stacks for a zone - the first can only be
+ * controlled from the global zone, and the second is owned by
+ * the zone itself. There is no need to create a GZ-controlled
+ * stack for the global zone, since we're already in the global
+ * zone. See the "GZ-controlled and per-zone stacks" comment block in
+ * ip_fil_solaris.c for details.
+ */
+ if (zid != GLOBAL_ZONEID)
+ ifs = ipf_stack_create_one(id, zid, B_TRUE, NULL);
+
+ return (ipf_stack_create_one(id, zid, B_FALSE, ifs));
+}
/*
- * This function should only ever be used to find the pointer to the
- * ipfilter stack structure for the zone that is currently being
- * executed... so if you're running in the context of zone 1, you
- * should not attempt to find the ipf_stack_t for zone 0 or 2 or
- * anything else but 1. In that way, the returned pointer is safe
- * as it will only be nuked when the instance is destroyed as part
- * of the final shutdown of a zone.
+ * Find an ipfilter stack for the given zone. Return the GZ-controlled or
+ * per-zone stack if set by an earlier SIOCIPFZONESET ioctl call. See the
+ * "GZ-controlled and per-zone stacks" comment block in ip_fil_solaris.c for
+ * details.
+ *
+ * This function returns with the ipf_stack_t's ifs_ipf_global
+ * read lock held (if the stack is found). See the "ipfilter kernel module
+ * mutexes and locking" comment block at the top of this file.
*/
ipf_stack_t *
-ipf_find_stack(const zoneid_t zone)
+ipf_find_stack(const zoneid_t orig_zone, ipf_devstate_t *isp)
{
ipf_stack_t *ifs;
+ boolean_t gz_stack;
+ zoneid_t zone;
+
+ /*
+ * If we're in the GZ, determine if we're acting on a zone's stack,
+ * and whether or not that stack is the GZ-controlled or in-zone
+ * one. See the "GZ and per-zone stacks" note at the top of this
+ * file.
+ */
+ if (orig_zone == GLOBAL_ZONEID &&
+ (isp->ipfs_zoneid != IPFS_ZONE_UNSET)) {
+ /* Global zone, and we've set the zoneid for this fd already */
+
+ if (orig_zone == isp->ipfs_zoneid) {
+ /* There's only a per-zone stack for the GZ */
+ gz_stack = B_FALSE;
+ } else {
+ gz_stack = isp->ipfs_gz;
+ }
+
+ zone = isp->ipfs_zoneid;
+ } else {
+ /*
+ * Non-global zone or GZ without having set a zoneid: act on
+ * the per-zone stack of the zone that this ioctl originated
+ * from.
+ */
+ gz_stack = B_FALSE;
+ zone = orig_zone;
+ }
mutex_enter(&ipf_stack_lock);
for (ifs = ipf_stacks; ifs != NULL; ifs = ifs->ifs_next) {
- if (ifs->ifs_zone == zone)
+ if (ifs->ifs_zone == zone && ifs->ifs_gz_controlled == gz_stack)
break;
}
+
+ if (ifs != NULL) {
+ READ_ENTER(&ifs->ifs_ipf_global);
+ }
mutex_exit(&ipf_stack_lock);
return (ifs);
}
-
static int ipf_detach_check_zone(ipf_stack_t *ifs)
{
/*
@@ -495,7 +600,8 @@ static int ipf_detach_check_all()
/*
- * Destroy things for ipf for one stack.
+ * Remove ipf kstats for both the per-zone ipf stack and the
+ * GZ-controlled stack for the same zone, if it exists.
*/
/* ARGSUSED */
static void
@@ -503,6 +609,15 @@ ipf_stack_shutdown(const netid_t id, void *arg)
{
ipf_stack_t *ifs = (ipf_stack_t *)arg;
+ /*
+ * The GZ-controlled stack
+ */
+ if (ifs->ifs_gz_cont_ifs != NULL)
+ ipf_kstat_fini(ifs->ifs_gz_cont_ifs);
+
+ /*
+ * The per-zone stack
+ */
ipf_kstat_fini(ifs);
}
@@ -512,13 +627,12 @@ ipf_stack_shutdown(const netid_t id, void *arg)
*/
/* ARGSUSED */
static void
-ipf_stack_destroy(const netid_t id, void *arg)
+ipf_stack_destroy_one(const netid_t id, ipf_stack_t *ifs)
{
- ipf_stack_t *ifs = (ipf_stack_t *)arg;
timeout_id_t tid;
#ifdef IPFDEBUG
- (void) printf("ipf_stack_destroy(%p)\n", (void *)ifs);
+ (void) printf("ipf_stack_destroy_one(%p)\n", (void *)ifs);
#endif
/*
@@ -546,7 +660,7 @@ ipf_stack_destroy(const netid_t id, void *arg)
WRITE_ENTER(&ifs->ifs_ipf_global);
if (ipldetach(ifs) != 0) {
- printf("ipf_stack_destroy: ipldetach failed\n");
+ printf("ipf_stack_destroy_one: ipldetach failed\n");
}
ipftuneable_free(ifs);
@@ -560,6 +674,30 @@ ipf_stack_destroy(const netid_t id, void *arg)
}
+/*
+ * Destroy things for ipf for both the per-zone ipf stack and the
+ * GZ-controlled stack for the same zone, if it exists. See the "GZ-controlled
+ * and per-zone stacks" comment block in ip_fil_solaris.c for details.
+ */
+/* ARGSUSED */
+static void
+ipf_stack_destroy(const netid_t id, void *arg)
+{
+ ipf_stack_t *ifs = (ipf_stack_t *)arg;
+
+ /*
+ * The GZ-controlled stack
+ */
+ if (ifs->ifs_gz_cont_ifs != NULL)
+ ipf_stack_destroy_one(id, ifs->ifs_gz_cont_ifs);
+
+ /*
+ * The per-zone stack
+ */
+ ipf_stack_destroy_one(id, ifs);
+}
+
+
static int ipf_attach(dip, cmd)
dev_info_t *dip;
ddi_attach_cmd_t cmd;
@@ -586,27 +724,39 @@ ddi_attach_cmd_t cmd;
(void) ipf_property_g_update(dip);
+ if (ddi_soft_state_init(&ipf_state, sizeof (ipf_devstate_t), 1)
+ != 0) {
+ ddi_prop_remove_all(dip);
+ return (DDI_FAILURE);
+ }
+
for (i = 0; ((s = ipf_devfiles[i]) != NULL); i++) {
s = strrchr(s, '/');
if (s == NULL)
continue;
s++;
if (ddi_create_minor_node(dip, s, S_IFCHR, i,
- DDI_PSEUDO, 0) ==
- DDI_FAILURE) {
- ddi_remove_minor_node(dip, NULL);
+ DDI_PSEUDO, 0) == DDI_FAILURE)
goto attach_failed;
- }
}
ipf_dev_info = dip;
ipfncb = net_instance_alloc(NETINFO_VERSION);
+ if (ipfncb == NULL)
+ goto attach_failed;
+
ipfncb->nin_name = "ipf";
ipfncb->nin_create = ipf_stack_create;
ipfncb->nin_destroy = ipf_stack_destroy;
ipfncb->nin_shutdown = ipf_stack_shutdown;
- i = net_instance_register(ipfncb);
+ if (net_instance_register(ipfncb) == DDI_FAILURE) {
+ net_instance_free(ipfncb);
+ goto attach_failed;
+ }
+
+ ipf_minor = vmem_create("ipf_minor", (void *)1, UINT32_MAX - 1,
+ 1, NULL, NULL, NULL, 0, VM_SLEEP | VMC_IDENTIFIER);
#ifdef IPFDEBUG
cmn_err(CE_CONT, "IP Filter:stack_create callback_reg=%d", i);
@@ -619,7 +769,9 @@ ddi_attach_cmd_t cmd;
}
attach_failed:
+ ddi_remove_minor_node(dip, NULL);
ddi_prop_remove_all(dip);
+ ddi_soft_state_fini(&ipf_state);
return (DDI_FAILURE);
}
@@ -652,6 +804,9 @@ ddi_detach_cmd_t cmd;
return (DDI_FAILURE);
}
+ vmem_destroy(ipf_minor);
+ ddi_soft_state_fini(&ipf_state);
+
(void) net_instance_unregister(ipfncb);
net_instance_free(ipfncb);
diff --git a/usr/src/uts/intel/ipf/ipf.global-objs.debug64 b/usr/src/uts/intel/ipf/ipf.global-objs.debug64
index 203dd14416..663613cee3 100644
--- a/usr/src/uts/intel/ipf/ipf.global-objs.debug64
+++ b/usr/src/uts/intel/ipf/ipf.global-objs.debug64
@@ -22,11 +22,33 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
+# Copyright 2013 Joyent, Inc. All rights reserved
+#
fr_availfuncs
fr_features
fr_objbytes
hdrsizes
+hook4_in
+hook4_in_gz
+hook4_loop_in
+hook4_loop_in_gz
+hook4_loop_out
+hook4_loop_out_gz
+hook4_nicevents
+hook4_nicevents_gz
+hook4_out
+hook4_out_gz
+hook6_in
+hook6_in_gz
+hook6_loop_in
+hook6_loop_in_gz
+hook6_loop_out
+hook6_loop_out_gz
+hook6_nicevents
+hook6_nicevents_gz
+hook6_out
+hook6_out_gz
icmpreplytype4
icmpreplytype6
icmptoicmp6types
@@ -37,10 +59,12 @@ ipf_cb_ops
ipf_dev_info
ipf_devfiles
ipf_kstat_tmp
+ipf_minor
ipf_ops
ipf_proxy_debug
ipf_stack_lock
ipf_stacks
+ipf_state
ipfilter_version
ipfncb
ipl_magic
diff --git a/usr/src/uts/sparc/ipf/ipf.global-objs.debug64 b/usr/src/uts/sparc/ipf/ipf.global-objs.debug64
index 61566e8b65..663613cee3 100644
--- a/usr/src/uts/sparc/ipf/ipf.global-objs.debug64
+++ b/usr/src/uts/sparc/ipf/ipf.global-objs.debug64
@@ -22,11 +22,33 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
+# Copyright 2013 Joyent, Inc. All rights reserved
+#
fr_availfuncs
fr_features
fr_objbytes
hdrsizes
+hook4_in
+hook4_in_gz
+hook4_loop_in
+hook4_loop_in_gz
+hook4_loop_out
+hook4_loop_out_gz
+hook4_nicevents
+hook4_nicevents_gz
+hook4_out
+hook4_out_gz
+hook6_in
+hook6_in_gz
+hook6_loop_in
+hook6_loop_in_gz
+hook6_loop_out
+hook6_loop_out_gz
+hook6_nicevents
+hook6_nicevents_gz
+hook6_out
+hook6_out_gz
icmpreplytype4
icmpreplytype6
icmptoicmp6types
@@ -37,10 +59,12 @@ ipf_cb_ops
ipf_dev_info
ipf_devfiles
ipf_kstat_tmp
+ipf_minor
ipf_ops
ipf_proxy_debug
ipf_stack_lock
ipf_stacks
+ipf_state
ipfilter_version
ipfncb
ipl_magic
@@ -56,9 +80,9 @@ rcsid
sccsid
secopt
tcpopts
+lastx
_drand48_a
_drand48_c
_drand48_x
init48done
seed_lock
-lastx