summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorRob Gulewich <robert.gulewich@joyent.com>2013-10-31 08:30:21 +0000
committerRob Gulewich <robert.gulewich@joyent.com>2013-10-31 08:48:00 +0000
commit9e752db2cdf20c29448931b05df26b85cb493303 (patch)
treeaec5a05a255c03f4dd58244a1511f8ffcf2eab15 /usr/src
parentb0f1f47849931c946259bb874d1fc19d9513be7f (diff)
downloadillumos-joyent-9e752db2cdf20c29448931b05df26b85cb493303.tar.gz
OS-2544 ipf rules from the GZ should be add to in-zone rules, not replace them
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/ipf/tools/ipf.c6
-rw-r--r--usr/src/cmd/ipf/tools/ipfs.c11
-rw-r--r--usr/src/cmd/ipf/tools/ipfstat.c20
-rw-r--r--usr/src/cmd/ipf/tools/ipfzone.c38
-rw-r--r--usr/src/cmd/ipf/tools/ipfzone.h3
-rw-r--r--usr/src/cmd/ipf/tools/ipmon.c10
-rw-r--r--usr/src/cmd/ipf/tools/ipnat.c11
-rw-r--r--usr/src/cmd/ipf/tools/ippool.c62
-rw-r--r--usr/src/man/man1m/ipf.1m27
-rw-r--r--usr/src/man/man1m/ipfs.1m37
-rw-r--r--usr/src/man/man1m/ipfstat.1m24
-rw-r--r--usr/src/man/man1m/ipmon.1m25
-rw-r--r--usr/src/man/man1m/ipnat.1m24
-rw-r--r--usr/src/man/man1m/ippool.1m36
-rw-r--r--usr/src/uts/common/inet/ipf/fil.c11
-rw-r--r--usr/src/uts/common/inet/ipf/ip_fil_solaris.c219
-rw-r--r--usr/src/uts/common/inet/ipf/netinet/ip_fil.h8
-rw-r--r--usr/src/uts/common/inet/ipf/netinet/ipf_stack.h3
-rw-r--r--usr/src/uts/common/inet/ipf/solaris.c40
19 files changed, 484 insertions, 131 deletions
diff --git a/usr/src/cmd/ipf/tools/ipf.c b/usr/src/cmd/ipf/tools/ipf.c
index 5f1406fbf5..97bee67b26 100644
--- a/usr/src/cmd/ipf/tools/ipf.c
+++ b/usr/src/cmd/ipf/tools/ipf.c
@@ -6,7 +6,7 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#ifdef __FreeBSD__
@@ -68,7 +68,7 @@ static ioctlfunc_t iocfunctions[IPL_LOGSIZE] = { ioctl, ioctl, ioctl,
static void usage()
{
- fprintf(stderr, "usage: ipf [-6AdDEInoPrRsvVyzZ] %s %s %s",
+ 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>]");
#if SOLARIS
@@ -85,7 +85,7 @@ int argc;
char *argv[];
{
int c;
- const char *optstr = "6Ac:dDEf:F:Il:noPrRsT:vVyzZ";
+ const char *optstr = "6Ac:dDEf:F:GIl:noPrRsT:vVyzZ";
if (argc < 2)
usage();
diff --git a/usr/src/cmd/ipf/tools/ipfs.c b/usr/src/cmd/ipf/tools/ipfs.c
index b5b9eebac1..72296a09d0 100644
--- a/usr/src/cmd/ipf/tools/ipfs.c
+++ b/usr/src/cmd/ipf/tools/ipfs.c
@@ -6,7 +6,7 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#ifdef __FreeBSD__
@@ -92,7 +92,7 @@ char *progname;
void usage()
{
#if SOLARIS
- const char *zoneopt = "[-z zonename] ";
+ const char *zoneopt = "[-G|-z zonename] ";
#else
const char *zoneopt = "";
#endif
@@ -230,7 +230,7 @@ char *argv[];
char *dirname = NULL, *filename = NULL, *ifs = NULL;
progname = argv[0];
- while ((c = getopt(argc, argv, "d:f:lNnSRruvWwz:")) != -1)
+ while ((c = getopt(argc, argv, "d:f:G:lNnSRruvWwz:")) != -1)
switch (c)
{
case 'd' :
@@ -245,6 +245,11 @@ char *argv[];
else
usage();
break;
+#if SOLARIS
+ case 'G' :
+ setzonename_global(optarg);
+ break;
+#endif
case 'i' :
ifs = optarg;
set = 1;
diff --git a/usr/src/cmd/ipf/tools/ipfstat.c b/usr/src/cmd/ipf/tools/ipfstat.c
index 916d75277b..49ee7cd23d 100644
--- a/usr/src/cmd/ipf/tools/ipfstat.c
+++ b/usr/src/cmd/ipf/tools/ipfstat.c
@@ -6,7 +6,7 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#ifdef __FreeBSD__
@@ -184,7 +184,7 @@ char *name;
fprintf(stderr, " %s -t [-C] ", name);
#endif
#ifdef SOLARIS
- fprintf(stderr, "[-z zonename] ");
+ fprintf(stderr, "[-G|-z zonename] ");
#endif
fprintf(stderr, "[-D destination address] [-P protocol] [-S source address] [-T refresh time]\n");
exit(1);
@@ -216,9 +216,9 @@ char *argv[];
u_32_t frf;
#ifdef USE_INET6
- options = "6aACdfghIilnostvD:M:N:P:RS:T:z:";
+ options = "6aACdfgG:hIilnostvD:M:N:P:RS:T:z:";
#else
- options = "aACdfghIilnostvD:M:N:P:RS:T:z:";
+ options = "aACdfgG:hIilnostvD:M:N:P:RS:T:z:";
#endif
saddr.in4.s_addr = INADDR_ANY; /* default any v4 source addr */
@@ -232,13 +232,20 @@ char *argv[];
opterr = 0;
/*
- * Parse these three 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' :
+#if SOLARIS
+ setzonename_global(optarg);
+#else
+ usage(argv[0]);
+#endif
+ break;
case 'M' :
memf = optarg;
live_kernel = 0;
@@ -252,7 +259,6 @@ char *argv[];
setzonename(optarg);
#else
usage(argv[0]);
- break;
#endif
break;
}
@@ -327,6 +333,8 @@ char *argv[];
case 'g' :
opts |= OPT_GROUPS;
break;
+ case 'G' :
+ break;
case 'h' :
opts |= OPT_HITS;
break;
diff --git a/usr/src/cmd/ipf/tools/ipfzone.c b/usr/src/cmd/ipf/tools/ipfzone.c
index 1dabbcd447..c52b3e879d 100644
--- a/usr/src/cmd/ipf/tools/ipfzone.c
+++ b/usr/src/cmd/ipf/tools/ipfzone.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012 Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
* Use is subject to license terms.
*
* See the IPFILTER.LICENCE file for details on licensing.
@@ -17,7 +17,8 @@
#include "ipfzone.h"
static ipfzoneobj_t ipzo;
-static int do_setzone = 0;
+static boolean_t do_setzone = 0;
+static int num_setzones = 0;
extern int errno;
extern int optind;
@@ -30,11 +31,17 @@ extern char *optarg;
void
getzonearg(int argc, char *argv[], const char *optstr)
{
+ int c;
+
/*
- * Let getopt figure out if the last argument belongs to a flag or is
+ * 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 (getopt(argc, argv, optstr) != -1) { }
+ while ((c = getopt(argc, argv, optstr)) != -1) {
+ if (c == 'G')
+ ipzo.ipfz_gz = 1;
+ }
if (optind < argc)
setzonename(argv[optind]);
@@ -55,6 +62,9 @@ getzoneopt(int argc, char *argv[], const char *optstr)
int c;
while ((c = getopt(argc, argv, optstr)) != -1) {
+ if (c == 'G')
+ setzonename_global(optarg);
+
if (c == 'z')
setzonename(optarg);
}
@@ -73,7 +83,19 @@ void
setzonename(const char *zonename)
{
memcpy(ipzo.ipfz_zonename, zonename, sizeof (ipzo.ipfz_zonename));
- do_setzone = 1;
+ do_setzone = B_TRUE;
+ num_setzones++;
+}
+
+/*
+ * Set the zonename in ipfo, and the gz flag to indicate that we want to
+ * act on the GZ-controlled stack
+ */
+void
+setzonename_global(const char *zonename)
+{
+ setzonename(zonename);
+ ipzo.ipfz_gz = 1;
}
/*
@@ -85,6 +107,12 @@ 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 (ioctl(fd, SIOCIPFZONESET, &ipzo) == -1) {
switch (errno) {
case ENODEV:
diff --git a/usr/src/cmd/ipf/tools/ipfzone.h b/usr/src/cmd/ipf/tools/ipfzone.h
index a62747af7d..ca6f42ec6a 100644
--- a/usr/src/cmd/ipf/tools/ipfzone.h
+++ b/usr/src/cmd/ipf/tools/ipfzone.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012 Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
* Use is subject to license terms.
*
* See the IPFILTER.LICENCE file for details on licensing.
@@ -12,5 +12,6 @@ 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 0c025b8c56..cf10eece9b 100644
--- a/usr/src/cmd/ipf/tools/ipmon.c
+++ b/usr/src/cmd/ipf/tools/ipmon.c
@@ -6,7 +6,7 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
@@ -1346,7 +1346,7 @@ static void usage(prog)
char *prog;
{
#if SOLARIS
- const char *zoneopt = " [-z zonename]";
+ const char *zoneopt = " [-G|-z zonename]";
#else
const char *zoneopt = "";
#endif
@@ -1461,7 +1461,7 @@ char *argv[];
char buf[DEFAULT_IPFLOGSIZE], *iplfile[3], *s;
extern int optind;
extern char *optarg;
- const char *optstr = "?abB:C:Df:FhnN:o:O:pP:sS:tvxXz:";
+ 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;
@@ -1509,6 +1509,10 @@ char *argv[];
flushlogs(iplfile[1], log);
flushlogs(iplfile[2], log);
break;
+#if SOLARIS
+ case 'G' :
+ break;
+#endif
case 'n' :
opts |= OPT_RESOLVE;
break;
diff --git a/usr/src/cmd/ipf/tools/ipnat.c b/usr/src/cmd/ipf/tools/ipnat.c
index 1f320a606f..a7e37b0295 100644
--- a/usr/src/cmd/ipf/tools/ipnat.c
+++ b/usr/src/cmd/ipf/tools/ipnat.c
@@ -8,7 +8,7 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#include <stdio.h>
@@ -103,7 +103,7 @@ char *name;
{
fprintf(stderr, "Usage: %s [-CdFhlnrRsv] [-f filename]", name);
#if SOLARIS
- fprintf(stderr, " [-z zonename]\n");
+ fprintf(stderr, " [-G|-z zonename]\n");
#else
fprintf(stderr, "\n");
#endif
@@ -128,7 +128,7 @@ char *argv[];
kernel = NULL;
mode = O_RDWR;
- while ((c = getopt(argc, argv, "CdFf:hlM:N:nrRsvz:")) != -1)
+ while ((c = getopt(argc, argv, "CdFf:G:hlM:N:nrRsvz:")) != -1)
switch (c)
{
case 'C' :
@@ -143,6 +143,11 @@ char *argv[];
case 'F' :
opts |= OPT_FLUSH;
break;
+#if SOLARIS
+ case 'G' :
+ setzonename_global(optarg);
+ break;
+#endif
case 'h' :
opts |=OPT_HITS;
break;
diff --git a/usr/src/cmd/ipf/tools/ippool.c b/usr/src/cmd/ipf/tools/ippool.c
index adf6ba7b69..d918af8e10 100644
--- a/usr/src/cmd/ipf/tools/ippool.c
+++ b/usr/src/cmd/ipf/tools/ippool.c
@@ -6,7 +6,7 @@
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -78,7 +78,7 @@ void usage(prog)
char *prog;
{
#if SOLARIS
- const char *zoneopt = "[-z zonename] ";
+ const char *zoneopt = "[-G|-z zonename] ";
#else
const char *zoneopt = "";
#endif
@@ -156,13 +156,19 @@ char *argv[];
role = IPL_LOGIPF;
bzero((char *)&node, sizeof(node));
- while ((c = getopt(argc, argv, "di:m:no:Rvz:")) != -1)
+ while ((c = getopt(argc, argv, "di:G:m:no:Rvz:")) != -1)
switch (c)
{
case 'd' :
opts |= OPT_DEBUG;
ippool_yydebug++;
break;
+ case 'G' :
+#if SOLARIS
+ setzonename_global(optarg);
+#else
+ usage(argv[0]);
+#endif
case 'i' :
s = strchr(optarg, '/');
if (s == NULL)
@@ -198,6 +204,13 @@ char *argv[];
case 'v' :
opts |= OPT_VERBOSE;
break;
+ case 'z' :
+#if SOLARIS
+ setzonename(optarg);
+#else
+ usage(argv[0]);
+#endif
+ break;
}
if (opts & OPT_DEBUG)
@@ -235,13 +248,19 @@ char *argv[];
bzero((char *)&iph, sizeof(iph));
bzero((char *)&pool, sizeof(pool));
- while ((c = getopt(argc, argv, "dm:no:RS:t:vz:")) != -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' :
+#if SOLARIS
+ setzonename_global(optarg);
+#else
+ usage(argv[0]);
+#endif
case 'm' :
poolname = optarg;
break;
@@ -271,6 +290,13 @@ char *argv[];
case 'v' :
opts |= OPT_VERBOSE;
break;
+ case 'z' :
+#if SOLARIS
+ setzonename(optarg);
+#else
+ usage(argv[0]);
+#endif
+ break;
}
if (opts & OPT_DEBUG)
@@ -324,13 +350,20 @@ char *argv[], *infile;
infile = optarg;
- while ((c = getopt(argc, argv, "dnRuvz:")) != -1)
+ while ((c = getopt(argc, argv, "dG:nRuvz:")) != -1)
switch (c)
{
case 'd' :
opts |= OPT_DEBUG;
ippool_yydebug++;
break;
+ case 'G' :
+#if SOLARIS
+ setzonename_global(optarg);
+#else
+ usage(argv[0]);
+#endif
+ break;
case 'n' :
opts |= OPT_DONOTHING;
break;
@@ -394,12 +427,19 @@ char *argv[];
poolname = NULL;
role = IPL_LOGALL;
- while ((c = getopt(argc, argv, "dm:M:N:o:Rt:vz:")) != -1)
+ while ((c = getopt(argc, argv, "dG:m:M:N:o:Rt:vz:")) != -1)
switch (c)
{
case 'd' :
opts |= OPT_DEBUG;
break;
+ case 'G' :
+#if SOLARIS
+ setzonename_global(optarg);
+#else
+ usage(argv[0]);
+#endif
+ break;
case 'm' :
poolname = optarg;
break;
@@ -657,12 +697,19 @@ char *argv[];
bzero((char *)&op, sizeof(op));
- while ((c = getopt(argc, argv, "dM:N:o:t:vz:")) != -1)
+ while ((c = getopt(argc, argv, "dG:M:N:o:t:vz:")) != -1)
switch (c)
{
case 'd' :
opts |= OPT_DEBUG;
break;
+ case 'G' :
+#if SOLARIS
+ setzonename_global(optarg);
+#else
+ usage(argv[0]);
+#endif
+ break;
case 'M' :
live_kernel = 0;
core = optarg;
@@ -695,6 +742,7 @@ char *argv[];
#else
usage(argv[0]);
#endif
+ break;
}
if (opts & OPT_DEBUG)
diff --git a/usr/src/man/man1m/ipf.1m b/usr/src/man/man1m/ipf.1m
index 63fb6a460d..93267db577 100644
--- a/usr/src/man/man1m/ipf.1m
+++ b/usr/src/man/man1m/ipf.1m
@@ -2,14 +2,14 @@
.\" 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.
-.\" Portions Copyright (c) 2012, Joyent, Inc. All Rights Reserved.
-.TH IPF 1M "Nov 26, 2012"
+.\" Portions Copyright (c) 2013, Joyent, Inc. All Rights Reserved.
+.TH IPF 1M "Oct 30, 2013"
.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...] [\fIzonename\fR]
.fi
@@ -258,6 +258,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
@@ -463,10 +474,18 @@ affect fragment or state statistics.
.SH ZONES
.sp
.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.
+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.
.SH FILES
.sp
diff --git a/usr/src/man/man1m/ipfs.1m b/usr/src/man/man1m/ipfs.1m
index 92006438b3..d54777e068 100644
--- a/usr/src/man/man1m/ipfs.1m
+++ b/usr/src/man/man1m/ipfs.1m
@@ -2,44 +2,44 @@
.\" 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.
-.\" Portions Copyright (c) 2012, Joyent, Inc. All Rights Reserved.
-.TH IPFS 1M "Nov 26, 2012"
+.\" 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-z\fR \fIzonename\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-z\fR \fIzonename\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-z\fR \fIzonename\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-z\fR \fIzonename\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-z\fR \fIzonename\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-z\fR \fIzonename\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-z\fR \fIzonename\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
@@ -171,9 +171,22 @@ beginning of this operation and unlocked once complete.
\fB\fB-z\fR\fR
.ad
.RS 6n
-Operate on the state information for the specified zone. If this option is not
-specified, the current zone is used. This command is only available in the
-Global Zone.
+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\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
diff --git a/usr/src/man/man1m/ipfstat.1m b/usr/src/man/man1m/ipfstat.1m
index 210191b852..65898ea804 100644
--- a/usr/src/man/man1m/ipfstat.1m
+++ b/usr/src/man/man1m/ipfstat.1m
@@ -2,8 +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.
-.\" Portions Copyright (c) 2012, Joyent, Inc. All Rights Reserved.
-.TH IPFSTAT 1M "Nov 26, 2012"
+.\" 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
@@ -15,7 +15,7 @@ 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-z\fR \fIzonename\fR]
+ [\fB-T\fR \fIrefreshtime\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR]
.fi
.SH DESCRIPTION
@@ -358,8 +358,22 @@ Turn verbose mode on. Displays additional debugging information.
\fB\fB-z\fR\fR
.ad
.RS 18n
-Report statistics for the specified zone. If this option is not specified,
-the current zone is used. This command is only available in the Global Zone.
+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\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
diff --git a/usr/src/man/man1m/ipmon.1m b/usr/src/man/man1m/ipmon.1m
index 4c8f17b287..86e8ff93e6 100644
--- a/usr/src/man/man1m/ipmon.1m
+++ b/usr/src/man/man1m/ipmon.1m
@@ -2,15 +2,15 @@
.\" 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.
-.\" Portions Copyright (c) 2012, Joyent, Inc. All Rights Reserved.
-.TH IPMON 1M "Nov 26, 2012"
+.\" 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] [\fB-z\fR \fIzonename\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
@@ -351,8 +351,23 @@ Show the log header record data in hex.
.ad
.sp .6
.RS 4n
-Monitor the specified zone. If this option is not specified, the current zone
-is used. This command is only available in the Global Zone.
+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\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
diff --git a/usr/src/man/man1m/ipnat.1m b/usr/src/man/man1m/ipnat.1m
index e9bd8c9fd5..6760b2598b 100644
--- a/usr/src/man/man1m/ipnat.1m
+++ b/usr/src/man/man1m/ipnat.1m
@@ -2,14 +2,14 @@
.\" 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.
-.\" Portions Copyright (c) 2012, Joyent, Inc. All Rights Reserved.
-.TH IPNAT 1M "Nov 26, 2012"
+.\" 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-z\fR \fIzonename\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
@@ -147,9 +147,21 @@ active rules/table entries.
\fB\fB-z\fR\fR
.ad
.RS 15n
-Operate on the IP NAT for the specified zone. If this option is not
-specified, the current zone is used. This command is only available in the
-Global Zone.
+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\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
diff --git a/usr/src/man/man1m/ippool.1m b/usr/src/man/man1m/ippool.1m
index 33d85ace4a..0bb1a2a690 100644
--- a/usr/src/man/man1m/ippool.1m
+++ b/usr/src/man/man1m/ippool.1m
@@ -9,50 +9,50 @@ ippool \- user interface to the IP Filter pools
.SH SYNOPSIS
.LP
.nf
-\fBippool\fR \fB-a\fR [\fB-dnv\fR] [\fB-z\fR \fIzonename\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-z\fR \fIzonename\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-z\fR \fIzonename\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-z\fR \fIzonename\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-z\fR \fIzonename\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-z\fR \fIzonename\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-z\fR \fIzonename\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-z\fR \fIzonename\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-z\fR \fIzonename\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
@@ -118,8 +118,22 @@ Turn verbose mode on.
\fB\fB-z\fR\fR
.ad
.RS 6n
-Manage IP pools for the specified zone. If this option is not specified, the
-current zone is used. This command is only available in the Global Zone.
+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\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"
diff --git a/usr/src/uts/common/inet/ipf/fil.c b/usr/src/uts/common/inet/ipf/fil.c
index e04d9242ea..86fc33a088 100644
--- a/usr/src/uts/common/inet/ipf/fil.c
+++ b/usr/src/uts/common/inet/ipf/fil.c
@@ -136,6 +136,9 @@ struct file;
# endif
#endif
#include "netinet/ipl.h"
+#if defined(SOLARIS) && defined(_KERNEL)
+#include <sys/sunddi.h>
+#endif
/* END OF INCLUDES */
#if !defined(lint)
@@ -5719,10 +5722,18 @@ void *data;
if (error != 0)
return EFAULT;
+ if (memchr(ipfzo.ipfz_zonename, NULL, ZONENAME_MAX) == NULL)
+ return EFAULT;
+
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;
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 1b23cfe497..5729be089c 100644
--- a/usr/src/uts/common/inet/ipf/ip_fil_solaris.c
+++ b/usr/src/uts/common/inet/ipf/ip_fil_solaris.c
@@ -5,7 +5,7 @@
*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#if !defined(lint)
@@ -106,6 +106,52 @@ u_long *ip_forwarding = NULL;
vmem_t *ipf_minor; /* minor number arena */
void *ipf_state; /* DDI state */
+/*
+ * GZ 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 */
/* Returns: int - 0 == success, else error. */
@@ -274,16 +320,35 @@ 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 hooks to run before the
+ * per-zone hooks, regardless of what order they're are installed.
+ */
+#define HOOK_INIT_GZ_BEFORE(x, fn, n, gzn, a) \
+ HOOK_INIT(x, fn, ifs->ifs_gz ? gzn : n, ifs); \
+ (x)->h_hint = ifs->ifs_gz ? HH_BEFORE : HH_AFTER; \
+ (x)->h_hintvalue = (uintptr_t) (ifs->ifs_gz ? 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 hooks to run after the
+ * per-zone hooks, regardless of what order they're are installed.
+ */
+#define HOOK_INIT_GZ_AFTER(x, fn, n, gzn, a) \
+ HOOK_INIT(x, fn, ifs->ifs_gz ? gzn : n, ifs); \
+ (x)->h_hint = ifs->ifs_gz ? HH_AFTER : HH_BEFORE; \
+ (x)->h_hintvalue = (uintptr_t) (ifs->ifs_gz ? 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
@@ -328,6 +393,7 @@ ipf_stack_t *ifs;
if (!ifs->ifs_hook4_loopback_out)
goto hookup_failed;
}
+
/*
* Add IPv6 hooks
*/
@@ -335,16 +401,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);
@@ -526,6 +592,7 @@ int *rp;
ipf_stack_t *ifs;
zoneid_t zid;
ipf_devstate_t *isp;
+ boolean_t gz_stack;
#ifdef IPFDEBUG
cmn_err(CE_CONT, "iplioctl(%x,%x,%x,%d,%x,%d)\n",
@@ -534,9 +601,8 @@ int *rp;
unit = getminor(dev);
isp = ddi_get_soft_state(ipf_state, unit);
- if (isp == NULL) {
+ if (isp == NULL)
return ENXIO;
- }
unit = isp->ipfs_minor;
zid = crgetzoneid(cp);
@@ -546,16 +612,38 @@ int *rp;
return EACCES;
}
- if (zid == GLOBAL_ZONEID)
- zid = isp->ipfs_zoneid;
+ /*
+ * 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 (zid == GLOBAL_ZONEID && (isp->ipfs_zoneid != -1)) {
+ /* Global zone, and we've set the zoneid for this fd already */
+
+ if (zid == isp->ipfs_zoneid) {
+ /* There's only a per-zone stack for the GZ */
+ gz_stack = B_FALSE;
+ } else {
+ gz_stack = isp->ipfs_gz;
+ }
+
+ zid = 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;
+ }
/*
* ipf_find_stack returns with a read lock on ifs_ipf_global
*/
- ifs = ipf_find_stack(zid);
- if (ifs == NULL) {
+ ifs = ipf_find_stack(zid, gz_stack);
+ if (ifs == NULL)
return ENXIO;
- }
if (ifs->ifs_fr_running <= 0) {
if (unit != IPL_LOGIPF) {
@@ -896,7 +984,7 @@ cred_t *cred;
VERIFY(isp != NULL);
isp->ipfs_minor = min;
- isp->ipfs_zoneid = GLOBAL_ZONEID;
+ isp->ipfs_zoneid = -1;
return 0;
}
@@ -941,26 +1029,48 @@ cred_t *cp;
minor_t unit;
zoneid_t zid;
ipf_devstate_t *isp;
+ boolean_t gz_stack;
unit = getminor(dev);
isp = ddi_get_soft_state(ipf_state, unit);
- if (isp == NULL) {
+ if (isp == NULL)
return ENXIO;
- }
unit = isp->ipfs_minor;
zid = crgetzoneid(cp);
- if (zid == GLOBAL_ZONEID) {
- zid = isp->ipfs_zoneid;
+
+ /*
+ * 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 (zid == GLOBAL_ZONEID && (isp->ipfs_zoneid != -1)) {
+ /* Global zone, and we've set the zoneid for this fd already */
+
+ if (zid == isp->ipfs_zoneid) {
+ /* There's only a per-zone stack for the GZ */
+ gz_stack = B_FALSE;
+ } else {
+ gz_stack = isp->ipfs_gz;
+ }
+
+ zid = 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;
}
/*
* ipf_find_stack returns with a read lock on ifs_ipf_global
*/
- ifs = ipf_find_stack(zid);
- if (ifs == NULL) {
+ ifs = ipf_find_stack(zid, gz_stack);
+ if (ifs == NULL)
return ENXIO;
- }
# ifdef IPFDEBUG
cmn_err(CE_CONT, "iplread(%x,%x,%x)\n", dev, uio, cp);
@@ -1000,26 +1110,48 @@ cred_t *cp;
minor_t unit;
zoneid_t zid;
ipf_devstate_t *isp;
+ boolean_t gz_stack;
unit = getminor(dev);
isp = ddi_get_soft_state(ipf_state, unit);
- if (isp == NULL) {
+ if (isp == NULL)
return ENXIO;
- }
unit = isp->ipfs_minor;
/*
* ipf_find_stack returns with a read lock on ifs_ipf_global
*/
zid = crgetzoneid(cp);
- if (zid == GLOBAL_ZONEID) {
- zid = isp->ipfs_zoneid;
+
+ /*
+ * 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 (zid == GLOBAL_ZONEID && (isp->ipfs_zoneid != -1)) {
+ /* Global zone, and we've set the zoneid for this fd already */
+
+ if (zid == isp->ipfs_zoneid) {
+ /* There's only a per-zone stack for the GZ */
+ gz_stack = B_FALSE;
+ } else {
+ gz_stack = isp->ipfs_gz;
+ }
+
+ zid = 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;
}
- ifs = ipf_find_stack(zid);
- if (ifs == NULL) {
+ ifs = ipf_find_stack(zid, gz_stack);
+ if (ifs == NULL)
return ENXIO;
- }
#ifdef IPFDEBUG
cmn_err(CE_CONT, "iplwrite(%x,%x,%x)\n", dev, uio, cp);
@@ -2117,7 +2249,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/netinet/ip_fil.h b/usr/src/uts/common/inet/ipf/netinet/ip_fil.h
index 5b4d125764..3de0047f3b 100644
--- a/usr/src/uts/common/inet/ipf/netinet/ip_fil.h
+++ b/usr/src/uts/common/inet/ipf/netinet/ip_fil.h
@@ -8,7 +8,7 @@
*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#ifndef __IP_FIL_H__
@@ -1176,13 +1176,15 @@ typedef struct ipfobj {
#include <sys/zone.h>
typedef struct ipfzoneobj {
- char ipfz_zonename[ZONENAME_MAX];
+ u_32_t ipfz_gz; /* GZ stack */
+ char ipfz_zonename[ZONENAME_MAX]; /* zone to act on */
} ipfzoneobj_t;
#if defined(_KERNEL)
typedef struct ipf_devstate {
zoneid_t ipfs_zoneid;
minor_t ipfs_minor;
+ boolean_t ipfs_gz;
} ipf_devstate_t;
#endif
@@ -1375,7 +1377,7 @@ 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 ipf_stack_t *ipf_find_stack(const zoneid_t zone, boolean_t gz);
extern int fr_check __P((struct ip *, int, void *, int, void *,
mblk_t **, ipf_stack_t *));
# if SOLARIS
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..0238d1fa09 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 2013 Joyent, Inc. All rights reserved.
*/
#ifndef __IPF_STACK_H__
@@ -43,6 +45,7 @@ struct ipf_stack {
struct ipf_stack **ifs_pnext;
netid_t ifs_netid;
zoneid_t ifs_zone;
+ boolean_t ifs_gz;
/* 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 c127185fea..307ab2cf78 100644
--- a/usr/src/uts/common/inet/ipf/solaris.c
+++ b/usr/src/uts/common/inet/ipf/solaris.c
@@ -6,7 +6,7 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
/*
@@ -266,10 +266,10 @@ 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,
+ (from_gz ? "inbound_gz" : "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,
@@ -280,7 +280,7 @@ ipf_kstat_init(ipf_stack_t *ifs)
}
ifs->ifs_kstatp[1] = net_kstat_create(ifs->ifs_netid, "ipf", 0,
- "outbound", "net", KSTAT_TYPE_NAMED,
+ (from_gz ? "outbound_gz" : "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,
@@ -414,12 +414,13 @@ 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;
#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);
@@ -443,8 +444,9 @@ 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 = from_gz;
+ ipf_kstat_init(ifs, from_gz);
#ifdef IPFDEBUG
cmn_err(CE_CONT, "IP Filter:stack_create zone=%d", ifs->ifs_zone);
@@ -472,19 +474,37 @@ ipf_stack_create(const netid_t id)
return (ifs);
}
+static void *
+ipf_stack_create(const netid_t id)
+{
+ ipf_stack_t *ifs;
+ 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.
+ */
+ if (zid != GLOBAL_ZONEID)
+ ipf_stack_create_one(id, zid, B_TRUE);
+
+ return ipf_stack_create_one(id, zid, B_FALSE);
+}
/*
* This function returns with the ipf_stack_t's ifs_ipf_global
* read lock held (if the stack is found).
*/
ipf_stack_t *
-ipf_find_stack(const zoneid_t zone)
+ipf_find_stack(const zoneid_t zone, const boolean_t gz)
{
ipf_stack_t *ifs;
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 == gz)
break;
}