diff options
author | Rob Gulewich <robert.gulewich@joyent.com> | 2012-11-13 18:24:41 +0000 |
---|---|---|
committer | Rob Gulewich <robert.gulewich@joyent.com> | 2012-11-28 02:24:22 +0000 |
commit | ec2a65d6980fcfc23a69a5564078d9bf879d42d8 (patch) | |
tree | 2d3c744d64586b6b44c34b304a76e9f801f3ef76 | |
parent | 1b9dcffe8b6daea095ed09ee539958f6ecd5fc1d (diff) | |
download | illumos-joyent-ec2a65d6980fcfc23a69a5564078d9bf879d42d8.tar.gz |
OS-777 ipfilter should support loading / modifying per-zone rules from the GZ
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
24 files changed, 801 insertions, 108 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..d91a831f44 100644 --- a/usr/src/cmd/ipf/lib/common/load_hash.c +++ b/usr/src/cmd/ipf/lib/common/load_hash.c @@ -7,6 +7,8 @@ * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -17,6 +19,10 @@ #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" +#if SOLARIS +#include "ipfzone.h" +#endif + static int hashfd = -1; @@ -35,6 +41,12 @@ ioctlfunc_t iocfunc; hashfd = open(IPLOOKUP_NAME, O_RDWR); if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0)) return -1; +#if SOLARIS + if (setzone(hashfd) != 0) { + close(hashfd); + return -1; + } +#endif 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..dd343f3ab1 100644 --- a/usr/src/cmd/ipf/lib/common/load_hashnode.c +++ b/usr/src/cmd/ipf/lib/common/load_hashnode.c @@ -7,6 +7,8 @@ * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -17,6 +19,10 @@ #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" +#if SOLARIS +#include "ipfzone.h" +#endif + static int hashfd = -1; @@ -34,6 +40,12 @@ ioctlfunc_t iocfunc; hashfd = open(IPLOOKUP_NAME, O_RDWR); if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0)) return -1; +#if SOLARIS + if (setzone(hashfd) != 0) { + close(hashfd); + return -1; + } +#endif 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..e09f77f6b4 100644 --- a/usr/src/cmd/ipf/lib/common/load_pool.c +++ b/usr/src/cmd/ipf/lib/common/load_pool.c @@ -7,6 +7,8 @@ * * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -17,6 +19,10 @@ #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" +#if SOLARIS +#include "ipfzone.h" +#endif + static int poolfd = -1; @@ -32,6 +38,12 @@ ioctlfunc_t iocfunc; poolfd = open(IPLOOKUP_NAME, O_RDWR); if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0)) return -1; +#if SOLARIS + if (setzone(poolfd) != 0) { + close(poolfd); + return -1; + } +#endif 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..37c7ef861e 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) 2012, Joyent, Inc. All rights reserved. */ #include <fcntl.h> @@ -12,6 +14,10 @@ #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" +#if SOLARIS +#include "ipfzone.h" +#endif + static int poolfd = -1; @@ -29,6 +35,12 @@ ioctlfunc_t iocfunc; poolfd = open(IPLOOKUP_NAME, O_RDWR); if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0)) return -1; +#if SOLARIS + if (setzone(poolfd) != 0) { + close(poolfd); + return -1; + } +#endif 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 71f81169f1..ccc5bf3c93 100644 --- a/usr/src/cmd/ipf/tools/Makefile.tools +++ b/usr/src/cmd/ipf/tools/Makefile.tools @@ -22,17 +22,19 @@ # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# 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..5f1406fbf5 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) 2012, Joyent, Inc. All rights reserved. */ #ifdef __FreeBSD__ @@ -21,6 +23,10 @@ #include <sys/ioctl.h> #include "netinet/ipl.h" +#ifdef SOLARIS +#include "ipfzone.h" +#endif + #if !defined(lint) static const char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-2000 Darren Reed"; static const char rcsid[] = "@(#)$Id: ipf.c,v 1.35.2.3 2004/12/15 18:27:17 darrenr Exp $"; @@ -62,9 +68,14 @@ 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 [-6AdDEInoPrRsvVyzZ] %s %s %s", "[-l block|pass|nomatch|state|nat]", "[-cc] [-F i|o|a|s|S|u]", "[-f filename] [-T <tuneopts>]"); +#if SOLARIS + fprintf(stderr, " [zonename]\n"); +#else + fprintf(stderr, "\n"); +#endif exit(1); } @@ -74,11 +85,20 @@ int argc; char *argv[]; { int c; + const char *optstr = "6Ac:dDEf:F:Il:noPrRsT:vVyzZ"; if (argc < 2) usage(); - while ((c = getopt(argc, argv, "6Ac:dDEf:F:Il:noPrRsT:vVyzZ")) != -1) { +#if SOLARIS + /* + * We need to set the zone name before calling the functions + * in the switch statement below + */ + getzonearg(argc, argv, optstr); +#endif + + while ((c = getopt(argc, argv, optstr)) != -1) { switch (c) { case '?' : @@ -187,6 +207,14 @@ int check; if ((fd = open(ipfdev, O_RDWR)) == -1) if ((fd = open(ipfdev, O_RDONLY)) == -1) perror("open device"); + +#if SOLARIS + if (setzone(fd) != 0) { + close(fd); + return -1; + } +#endif + return fd; } @@ -307,6 +335,13 @@ char *opt; if (opts & OPT_VERBOSE) printf("set state log flag\n"); xfd = open(IPSTATE_NAME, O_RDWR); +#if SOLARIS + if (xfd >= 0 && setzone(xfd) != 0) { + close(xfd); + xfd = -1; + } +#endif + if (xfd >= 0) { logopt = 0; if (ioctl(xfd, SIOCGETLG, &logopt)) @@ -324,6 +359,13 @@ char *opt; if (opts & OPT_VERBOSE) printf("set nat log flag\n"); xfd = open(IPNAT_NAME, O_RDWR); +#if SOLARIS + if (xfd >= 0 && setzone(xfd) != 0) { + close(xfd); + xfd = -1; + } +#endif + if (xfd >= 0) { logopt = 0; if (ioctl(xfd, SIOCGETLG, &logopt)) @@ -516,6 +558,14 @@ static int showversion() return 1; } +#if SOLARIS + if (setzone(vfd) != 0) { + close(vfd); + return 1; + } +#endif + + 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..b5b9eebac1 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) 2012, Joyent, Inc. All rights reserved. */ #ifdef __FreeBSD__ @@ -44,6 +46,9 @@ #include <resolv.h> #include "ipf.h" #include "netinet/ipl.h" +#if SOLARIS +#include "ipfzone.h" +#endif #if !defined(lint) static const char rcsid[] = "@(#)Id: ipfs.c,v 1.12 2003/12/01 01:56:53 darrenr Exp"; @@ -86,14 +91,21 @@ 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); +#if SOLARIS + const char *zoneopt = "[-z zonename] "; +#else + const char *zoneopt = ""; +#endif + 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 +230,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:lNnSRruvWwz:")) != -1) switch (c) { case 'd' : @@ -287,6 +299,11 @@ char *argv[]; rw = 3; set = 1; break; +#if SOLARIS + case 'z' : + setzonename(optarg); + break; +#endif case '?' : default : usage(); @@ -355,6 +372,14 @@ char *ipfdev; if ((fd = open(ipfdev, O_RDWR)) == -1) if ((fd = open(ipfdev, O_RDONLY)) == -1) perror("open device"); + +#if SOLARIS + if (setzone(fd) != 0) { + close(fd); + fd = -1; + } +#endif + return fd; } diff --git a/usr/src/cmd/ipf/tools/ipfstat.c b/usr/src/cmd/ipf/tools/ipfstat.c index 27b018e273..916d75277b 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) 2012, Joyent, Inc. All rights reserved. */ #ifdef __FreeBSD__ @@ -162,6 +164,10 @@ static int sort_dstip __P((const void *, const void *)); static int sort_dstpt __P((const void *, const void *)); #endif +#if SOLARIS +#include "ipfzone.h" +#endif + static void usage(name) char *name; @@ -177,6 +183,9 @@ char *name; #else fprintf(stderr, " %s -t [-C] ", name); #endif +#ifdef SOLARIS + fprintf(stderr, "[-z zonename] "); +#endif fprintf(stderr, "[-D destination address] [-P protocol] [-S source address] [-T refresh time]\n"); exit(1); } @@ -207,9 +216,9 @@ char *argv[]; u_32_t frf; #ifdef USE_INET6 - options = "6aACdfghIilnostvD:M:N:P:RS:T:"; + options = "6aACdfghIilnostvD:M:N:P:RS:T:z:"; #else - options = "aACdfghIilnostvD:M:N:P:RS:T:"; + options = "aACdfghIilnostvD:M:N:P:RS:T:z:"; #endif saddr.in4.s_addr = INADDR_ANY; /* default any v4 source addr */ @@ -223,7 +232,7 @@ char *argv[]; opterr = 0; /* - * Parse these two arguments now lest there be any buffer overflows + * Parse these three arguments now lest there be any buffer overflows * in the parsing of the rest. */ myoptind = optind; @@ -238,6 +247,14 @@ char *argv[]; kern = optarg; live_kernel = 0; break; + case 'z' : +#if SOLARIS + setzonename(optarg); +#else + usage(argv[0]); + break; +#endif + break; } } optind = myoptind; @@ -247,11 +264,23 @@ char *argv[]; perror("open(IPSTATE_NAME)"); exit(-1); } +#if SOLARIS + if (setzone(state_fd) != 0) { + close(state_fd); + exit(-1); + } +#endif if ((ipf_fd = open(device, O_RDONLY)) == -1) { fprintf(stderr, "open(%s)", device); perror(""); exit(-1); } +#if SOLARIS + if (setzone(ipf_fd) != 0) { + close(ipf_fd); + exit(-1); + } +#endif } if (kern != NULL || memf != NULL) { @@ -360,6 +389,8 @@ char *argv[]; opts |= OPT_VERBOSE; opts |= OPT_UNDEF; break; + case 'z' : + break; default : usage(argv[0]); break; @@ -482,6 +513,13 @@ u_32_t *frfp; exit(-1); } +#if SOLARIS + if (setzone(ipf_fd) != 0) { + close(ipf_fd); + exit(-1); + } +#endif + 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..e158c1d80f --- /dev/null +++ b/usr/src/cmd/ipf/tools/ipfzone.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2012 Joyent, Inc. All rights reserved. + * Use is subject to license terms. + * + * See the IPFILTER.LICENCE file for details on licensing. + */ + + +#include <zone.h> +#include <stdio.h> +#include <sys/ioctl.h> + +#include "ipfzone.h" + +static ipfzoneobj_t ipzo; +static int do_setzone = 0; + +extern int errno; +extern int optind; +extern char *optarg; + +/* + * Get the zonename if it's the last argument and set the zonename + * in ipfzo to it + */ +void +getzonearg(int argc, char *argv[], const char *optstr) +{ + /* + * Let getopt figure out if the last argument belongs to a flag or is + * actually a zonename. + */ + while (getopt(argc, argv, optstr) != -1) { } + + if (optind < argc) + setzonename(argv[optind]); + + /* + * Reset optind so the next getopt call will go through all of argv + * again. + */ + optind = 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; + + while ((c = getopt(argc, argv, optstr)) != -1) { + if (c == 'z') + setzonename(optarg); + } + + /* + * Reset optind so the next getopt call will go through all of argv + * again. + */ + optind = 1; +} + +/* + * Set the zonename in ipfzo to the given string + */ +void +setzonename(const char *zonename) +{ + memcpy(ipzo.ipfz_zonename, zonename, sizeof (ipzo.ipfz_zonename)); + do_setzone = 1; +} + +/* + * Set the zone that all further ioctls will operate on + */ +int +setzone(int fd) +{ + if (!do_setzone) + return (0); + + 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..f21c8f1c78 --- /dev/null +++ b/usr/src/cmd/ipf/tools/ipfzone.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2012 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__ + +#include <stdarg.h> +#include <net/if.h> +#include "netinet/ip_fil.h" + +void getzonearg(int, char *[], const char *); +void getzoneopt(int, char *[], const char *); +void setzonename(const char *); + +extern zoneid_t zoneid; + +#endif /* __IPFZONE_H__ */ diff --git a/usr/src/cmd/ipf/tools/ipmon.c b/usr/src/cmd/ipf/tools/ipmon.c index d4a351b015..0c025b8c56 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) 2012, Joyent, Inc. All rights reserved. */ @@ -78,6 +80,9 @@ #include "netinet/ip_state.h" #include "netinet/ip_proxy.h" #include "ipmon.h" +#if SOLARIS +#include "ipfzone.h" +#endif #if !defined(lint) static const char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed"; @@ -1340,8 +1345,13 @@ 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]]", +#if SOLARIS + const char *zoneopt = " [-z zonename]"; +#else + const char *zoneopt = ""; +#endif + fprintf(stderr, "%s: [-abDFhnpstvxX]%s %s %s %s %s %s %s\n", + prog, zoneopt, "[-N device]", "[ [-o [NSI]] [-O [NSI]]", "[-P pidfile]", "[-S device]", "[-f device]", "filename"); exit(1); @@ -1380,6 +1390,13 @@ FILE *log; exit(1); } +#if SOLARIS + if (setzone(fd) != 0) { + close(fd); + exit(1); + } +#endif + if (ioctl(fd, SIOCIPFFB, &flushed) == 0) { printf("%d bytes flushed from log buffer\n", flushed); @@ -1444,6 +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:"; fd[0] = fd[1] = fd[2] = -1; fdt[0] = fdt[1] = fdt[2] = -1; @@ -1451,7 +1469,15 @@ 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) +#if SOLARIS + /* + * We need to set the zone name before calling openlog in + * the switch statement below + */ + getzoneopt(argc, argv, optstr); +#endif + + while ((c = getopt(argc, argv, optstr)) != -1) switch (c) { case 'a' : @@ -1535,6 +1561,10 @@ char *argv[]; case 'X' : opts |= OPT_HEXHDR; break; +#if SOLARIS + case 'z' : + break; +#endif default : case 'h' : case '?' : @@ -1571,6 +1601,13 @@ char *argv[]; exit(1); /* NOTREACHED */ } + +#if SOLARIS + if (setzone(fd[i]) != 0) { + close(fd[i]); + exit(1); + } +#endif 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..1f320a606f 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) 2012, Joyent, Inc. All rights reserved. */ #include <stdio.h> @@ -56,6 +58,10 @@ #include "netinet/ipl.h" #include "kmem.h" +#if SOLARIS +#include "ipfzone.h" +#endif + #ifdef __hpux # define nlist nlist64 #endif @@ -95,7 +101,12 @@ int opts; void usage(name) char *name; { - fprintf(stderr, "Usage: %s [-CdFhlnrRsv] [-f filename]\n", name); + fprintf(stderr, "Usage: %s [-CdFhlnrRsv] [-f filename]", name); +#if SOLARIS + fprintf(stderr, " [-z zonename]\n"); +#else + fprintf(stderr, "\n"); +#endif exit(1); } @@ -117,7 +128,7 @@ char *argv[]; kernel = NULL; mode = O_RDWR; - while ((c = getopt(argc, argv, "CdFf:hlM:N:nrRsv")) != -1) + while ((c = getopt(argc, argv, "CdFf:hlM:N:nrRsvz:")) != -1) switch (c) { case 'C' : @@ -162,6 +173,11 @@ char *argv[]; case 'v' : opts |= OPT_VERBOSE; break; +#if SOLARIS + case 'z' : + setzonename(optarg); + break; +#endif default : usage(argv[0]); } @@ -194,6 +210,12 @@ char *argv[]; STRERROR(errno)); exit(1); } +#if SOLARIS + if (setzone(fd) != 0) { + close(fd); + exit(1); + } +#endif bzero((char *)&obj, sizeof(obj)); obj.ipfo_rev = IPFILTER_VERSION; diff --git a/usr/src/cmd/ipf/tools/ippool.c b/usr/src/cmd/ipf/tools/ippool.c index 5f18379420..adf6ba7b69 100644 --- a/usr/src/cmd/ipf/tools/ippool.c +++ b/usr/src/cmd/ipf/tools/ippool.c @@ -5,6 +5,8 @@ * * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -42,6 +44,10 @@ #include "netinet/ip_htable.h" #include "kmem.h" +#if SOLARIS +#include "ipfzone.h" +#endif + extern int ippool_yyparse __P((void)); extern int ippool_yydebug; extern FILE *ippool_yyin; @@ -71,15 +77,25 @@ int use_inet6 = 0; void usage(prog) char *prog; { +#if SOLARIS + const char *zoneopt = "[-z zonename] "; +#else + const char *zoneopt = ""; +#endif 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,7 +156,7 @@ 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:m:no:Rvz:")) != -1) switch (c) { case 'd' : @@ -219,7 +235,7 @@ 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, "dm:no:RS:t:vz:")) != -1) switch (c) { case 'd' : @@ -308,7 +324,7 @@ char *argv[], *infile; infile = optarg; - while ((c = getopt(argc, argv, "dnRuv")) != -1) + while ((c = getopt(argc, argv, "dnRuvz:")) != -1) switch (c) { case 'd' : @@ -327,6 +343,13 @@ char *argv[], *infile; case 'v' : opts |= OPT_VERBOSE; break; + case 'z' : +#if SOLARIS + setzonename(optarg); +#else + usage(argv[0]); +#endif + break; } if (opts & OPT_DEBUG) @@ -338,6 +361,12 @@ char *argv[], *infile; perror("open(IPLOOKUP_NAME)"); exit(1); } +#if SOLARIS + if (setzone(fd) != 0) { + close(fd); + exit(1); + } +#endif } if (ippool_parsefile(fd, infile, ioctl) != 0) @@ -365,7 +394,7 @@ char *argv[]; poolname = NULL; role = IPL_LOGALL; - while ((c = getopt(argc, argv, "dm:M:N:o:Rt:v")) != -1) + while ((c = getopt(argc, argv, "dm:M:N:o:Rt:vz:")) != -1) switch (c) { case 'd' : @@ -402,6 +431,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) @@ -413,6 +449,12 @@ char *argv[]; perror("open(IPLOOKUP_NAME)"); exit(1); } +#if SOLARIS + if (setzone(fd) != 0) { + close(fd); + exit(1); + } +#endif } bzero((char *)&op, sizeof(op)); @@ -615,7 +657,7 @@ char *argv[]; bzero((char *)&op, sizeof(op)); - while ((c = getopt(argc, argv, "dM:N:o:t:v")) != -1) + while ((c = getopt(argc, argv, "dM:N:o:t:vz:")) != -1) switch (c) { case 'd' : @@ -647,6 +689,12 @@ char *argv[]; case 'v' : opts |= OPT_VERBOSE; break; + case 'z' : +#if SOLARIS + setzonename(optarg); +#else + usage(argv[0]); +#endif } if (opts & OPT_DEBUG) @@ -658,6 +706,12 @@ char *argv[]; perror("open(IPLOOKUP_NAME)"); exit(1); } +#if SOLARIS + if (setzone(fd) != 0) { + close(fd); + exit(1); + } +#endif } if (type == IPLT_ALL || type == IPLT_POOL) { @@ -705,7 +759,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 +782,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) @@ -739,6 +800,12 @@ char *argv[]; perror("open(IPLOOKUP_NAME)"); exit(1); } +#if SOLARIS + if (setzone(fd) != 0) { + close(fd); + exit(1); + } +#endif } bzero((char *)&flush, sizeof(flush)); diff --git a/usr/src/man/man1m/ipf.1m b/usr/src/man/man1m/ipf.1m index 69cdacf689..63fb6a460d 100644 --- a/usr/src/man/man1m/ipf.1m +++ b/usr/src/man/man1m/ipf.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) 2009, Sun Microsystems Inc. All Rights Reserved. -.TH IPF 1M "Feb 25, 2009" +.\" Portions Copyright (c) 2012, Joyent, Inc. All Rights Reserved. +.TH IPF 1M "Nov 26, 2012" .SH NAME ipf \- alter packet filtering lists for IP packet input and output .SH SYNOPSIS @@ -10,7 +11,7 @@ ipf \- alter packet filtering lists for IP packet input and output .nf \fBipf\fR [\fB-6AdDEInoPRrsvVyzZ\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 @@ -459,6 +460,14 @@ Zero global statistics held in the kernel for filtering only. This does not affect fragment or state statistics. .RE +.SH ZONES +.sp +.LP +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. + .SH FILES .sp .ne 2 @@ -519,7 +528,7 @@ Interface Stability Committed .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 diff --git a/usr/src/man/man1m/ipfs.1m b/usr/src/man/man1m/ipfs.1m index ea2f16c065..92006438b3 100644 --- a/usr/src/man/man1m/ipfs.1m +++ b/usr/src/man/man1m/ipfs.1m @@ -2,43 +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. -.TH IPFS 1M "Apr 3, 2008" +.\" Portions Copyright (c) 2012, Joyent, Inc. All Rights Reserved. +.TH IPFS 1M "Nov 26, 2012" .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-z\fR \fIzonename\fR] [\fB-nv\fR] \fB-l\fR .fi .LP .nf -\fBipfs\fR [\fB-nv\fR] \fB-u\fR +\fBipfs\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-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-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-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-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-z\fR \fIzonename\fR] [\fB-nNSv\fR] \fB-f\fR \fIfilename\fR \fB-i\fR \fI<if1>\fR,\fI<if2>\fR .fi .SH DESCRIPTION @@ -164,6 +165,17 @@ 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\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. +.RE + .SH FILES .RS +4 .TP @@ -214,7 +226,8 @@ Interface Stability Committed .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 diff --git a/usr/src/man/man1m/ipfstat.1m b/usr/src/man/man1m/ipfstat.1m index 212de841a9..210191b852 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) 2012, Joyent, Inc. All Rights Reserved. +.TH IPFSTAT 1M "Nov 26, 2012" .SH NAME ipfstat \- reports on packet filter statistics and filter list .SH SYNOPSIS @@ -14,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-T\fR \fIrefreshtime\fR] [\fB-z\fR \fIzonename\fR] .fi .SH DESCRIPTION @@ -351,6 +352,16 @@ 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\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. +.RE + .SH FILES .RS +4 .TP @@ -396,7 +407,7 @@ Interface Stability Committed .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..4c8f17b287 100644 --- a/usr/src/man/man1m/ipmon.1m +++ b/usr/src/man/man1m/ipmon.1m @@ -2,14 +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. -.TH IPMON 1M "Apr 3, 2008" +.\" Portions Copyright (c) 2012, Joyent, Inc. All Rights Reserved. +.TH IPMON 1M "Nov 26, 2012" .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-z\fR \fIzonename\fR] [\fIfilename\fR] .fi .SH DESCRIPTION @@ -343,6 +344,17 @@ Show the packet data in hex. Show the log header record data in hex. .RE +.sp +.ne 2 +.na +\fB\fB-z\fR\fR +.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. +.RE + .SH FILES .RS +4 .TP @@ -382,7 +394,7 @@ Interface Stability Committed .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 diff --git a/usr/src/man/man1m/ipnat.1m b/usr/src/man/man1m/ipnat.1m index 6e36a50e26..e9bd8c9fd5 100644 --- a/usr/src/man/man1m/ipnat.1m +++ b/usr/src/man/man1m/ipnat.1m @@ -2,13 +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. -.TH IPNAT 1M "Apr 3, 2008" +.\" Portions Copyright (c) 2012, Joyent, Inc. All Rights Reserved. +.TH IPNAT 1M "Nov 26, 2012" .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-z\fR \fIzonename\fR] \fB-f\fR \fIfilename\fR .fi .SH DESCRIPTION @@ -140,6 +141,17 @@ Turn verbose mode on. Displays information relating to rule processing and active rules/table entries. .RE +.sp +.ne 2 +.na +\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. +.RE + .SH FILES .sp .ne 2 @@ -200,4 +212,5 @@ Interface Stability Committed .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..33d85ace4a 100644 --- a/usr/src/man/man1m/ippool.1m +++ b/usr/src/man/man1m/ippool.1m @@ -2,56 +2,57 @@ .\" 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-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-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-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-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-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-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-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-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-z\fR \fIzonename\fR] [\fB-M\fR \fIcore\fR] [\fB-N\fR \fInamelist\fR] .fi .SH DESCRIPTION @@ -111,6 +112,16 @@ would alter the currently running kernel. Turn verbose mode on. .RE +.sp +.ne 2 +.na +\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. +.RE + .SS "Instance-Specific Options" .sp .LP @@ -328,4 +339,5 @@ Interface Stability Committed .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/uts/common/inet/ipf/fil.c b/usr/src/uts/common/inet/ipf/fil.c index 3955d881e8..e04d9242ea 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) 2012, Joyent, Inc. All rights reserved. */ #if defined(KERNEL) || defined(_KERNEL) @@ -5696,6 +5698,39 @@ 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(SOLARIS) && 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 ((zone = zone_find_by_name(ipfzo.ipfz_zonename)) == NULL) + return ENODEV; + + idsp->ipfs_zoneid = zone->zone_id; + 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 75bac21ae4..1b23cfe497 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) 2012, Joyent, Inc. All rights reserved. */ #if !defined(lint) @@ -101,6 +103,8 @@ u_long *ip_forwarding = NULL; #endif #endif +vmem_t *ipf_minor; /* minor number arena */ +void *ipf_state; /* DDI state */ /* ------------------------------------------------------------------------ */ /* Function: ipldetach */ @@ -520,35 +524,52 @@ 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; + } + + if (zid == GLOBAL_ZONEID) + zid = isp->ipfs_zoneid; /* - * 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); + 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; @@ -849,7 +870,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); @@ -857,8 +880,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 = GLOBAL_ZONEID; + + return 0; } @@ -874,8 +914,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 @@ -893,30 +938,48 @@ cred_t *cp; { ipf_stack_t *ifs; int ret; + minor_t unit; + zoneid_t zid; + ipf_devstate_t *isp; + + unit = getminor(dev); + isp = ddi_get_soft_state(ipf_state, unit); + if (isp == NULL) { + return ENXIO; + } + unit = isp->ipfs_minor; + + zid = crgetzoneid(cp); + if (zid == GLOBAL_ZONEID) { + zid = isp->ipfs_zoneid; + } /* - * 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); + 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 */ @@ -934,20 +997,36 @@ register struct uio *uio; cred_t *cp; { ipf_stack_t *ifs; + minor_t unit; + zoneid_t zid; + 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); + zid = crgetzoneid(cp); + if (zid == GLOBAL_ZONEID) { + zid = isp->ipfs_zoneid; + } + + ifs = ipf_find_stack(zid); + 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; } @@ -958,6 +1037,7 @@ cred_t *cp; dev = dev; /* LINT */ uio = uio; /* LINT */ cp = cp; /* LINT */ + RWLOCK_EXIT(&ifs->ifs_ipf_global); return ENXIO; } diff --git a/usr/src/uts/common/inet/ipf/ip_log.c b/usr/src/uts/common/inet/ipf/ip_log.c index 1fe54f3a07..66e590eb4e 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) 2012, Joyent, Inc. All rights reserved. */ #include <sys/param.h> @@ -572,10 +574,15 @@ ipf_stack_t *ifs; while (ifs->ifs_iplt[unit] == NULL) { # if SOLARIS && defined(_KERNEL) + /* + * Prevent a deadlock with ipldetach() + */ + RWLOCK_EXIT(&ifs->ifs_ipf_global); if (!cv_wait_sig(&ifs->ifs_iplwait, &ifs->ifs_ipl_mutex.ipf_lk)) { 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/netinet/ip_fil.h b/usr/src/uts/common/inet/ipf/netinet/ip_fil.h index 0a2d6431d8..5b4d125764 100644 --- a/usr/src/uts/common/inet/ipf/netinet/ip_fil.h +++ b/usr/src/uts/common/inet/ipf/netinet/ip_fil.h @@ -7,6 +7,8 @@ * $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) 2012, Joyent, Inc. All rights reserved. */ #ifndef __IP_FIL_H__ @@ -107,6 +109,10 @@ #define SIOCDELFR SIOCRMAFR #define SIOCINSFR SIOCINAFR +#ifdef SOLARIS +# define SIOCIPFZONESET _IOWR('r', 97, struct ipfzoneobj) +#endif + /* * What type of table is getting flushed? */ @@ -1165,6 +1171,23 @@ typedef struct ipfobj { u_char ipfo_xxxpad[32]; /* reserved for future use */ } ipfobj_t; +#if defined(SOLARIS) + +#include <sys/zone.h> + +typedef struct ipfzoneobj { + char ipfz_zonename[ZONENAME_MAX]; +} ipfzoneobj_t; + +#if defined(_KERNEL) +typedef struct ipf_devstate { + zoneid_t ipfs_zoneid; + minor_t ipfs_minor; +} ipf_devstate_t; +#endif + +#endif + #define IPFOBJ_FRENTRY 0 /* struct frentry */ #define IPFOBJ_IPFSTAT 1 /* struct friostat */ #define IPFOBJ_IPFINFO 2 /* struct fr_info */ @@ -1576,6 +1599,10 @@ extern int ipf_earlydrop __P((int, ipftq_t *, int, ipf_stack_t *)); extern u_32_t ipf_random __P((void)); #endif +#if defined(SOLARIS) && 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/solaris.c b/usr/src/uts/common/inet/ipf/solaris.c index 1a1d94def5..c127185fea 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) 2012, 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, @@ -429,13 +474,8 @@ ipf_stack_create(const netid_t id) /* - * 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. + * 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) @@ -447,6 +487,10 @@ ipf_find_stack(const zoneid_t zone) if (ifs->ifs_zone == zone) break; } + + if (ifs != NULL) { + READ_ENTER(&ifs->ifs_ipf_global); + } mutex_exit(&ipf_stack_lock); return (ifs); } @@ -586,27 +630,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 +675,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 +710,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); |