94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich/*
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * Copyright (c) 2014 Joyent, Inc. All rights reserved.
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * Use is subject to license terms.
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich *
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * See the IPFILTER.LICENCE file for details on licensing.
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich */
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich#include <errno.h>
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich#include <net/if.h>
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich#include <stdio.h>
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich#include <string.h>
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich#include <unistd.h>
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich#include <zone.h>
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich#include "netinet/ip_fil.h"
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich#include "ipfzone.h"
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewichstatic ipfzoneobj_t ipzo;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewichstatic boolean_t do_setzone = 0;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewichstatic int num_setzones = 0;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewichextern int errno;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewichextern int opterr;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewichextern int optind;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewichextern char *optarg;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich/*
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * Get the zonename if it's the last argument and set the zonename
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * in ipfzo to it. This is used by ipf(1m) only - all of the other tools
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * specify the zone with the -z option, and therefore use getzoneopt() below.
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich */
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewichvoid
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewichgetzonearg(int argc, char *argv[], const char *optstr)
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich{
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich int c;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich /*
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * Don't warn about unknown options - let subsequent calls to
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * getopt() handle this.
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich */
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich opterr = 0;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich /*
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * getopt is also used here to set optind so that we can
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * determine if the last argument belongs to a flag or is
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * actually a zonename.
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich */
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich while ((c = getopt(argc, argv, optstr)) != -1) {
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich if (c == 'G')
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich ipzo.ipfz_gz = 1;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich }
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich if (optind < argc)
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich setzonename(argv[optind]);
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich /*
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * Reset optind and opterr so the next getopt call will go through all
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * of argv again and warn about unknown options.
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich */
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich optind = 1;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich opterr = 1;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich}
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich/*
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * Get a -z option from argv and set the zonename in ipfzo accordingly
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich */
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewichvoid
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewichgetzoneopt(int argc, char *argv[], const char *optstr)
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich{
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich int c;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich /*
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * Don't warn about unknown options - let subsequent calls to
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * getopt() handle this.
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich */
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich opterr = 0;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich while ((c = getopt(argc, argv, optstr)) != -1) {
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich if (c == 'G')
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich setzonename_global(optarg);
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich if (c == 'z')
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich setzonename(optarg);
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich }
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich /*
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * Reset optind and opterr so the next getopt call will go through all
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * of argv again and warn about unknown options.
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich */
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich optind = 1;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich opterr = 1;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich}
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich/*
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * Set the zonename in ipfzo to the given string: this is the zone all further
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * ioctls will act on.
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich */
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewichvoid
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewichsetzonename(const char *zonename)
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich{
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich memcpy(ipzo.ipfz_zonename, zonename, sizeof (ipzo.ipfz_zonename));
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich do_setzone = B_TRUE;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich num_setzones++;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich}
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich/*
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * Set the zonename in ipfo, and the gz flag. This indicates that we want all
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * further ioctls to act on the GZ-controlled stack for that zone.
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich */
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewichvoid
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewichsetzonename_global(const char *zonename)
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich{
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich setzonename(zonename);
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich ipzo.ipfz_gz = 1;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich}
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich/*
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * Set the zone that all further ioctls will operate on. See the "GZ-controlled
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * and per-zone stacks" note at the top of ip_fil_solaris.c for further
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich * explanation.
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich */
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewichint
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewichsetzone(int fd)
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich{
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich if (!do_setzone)
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich return (0);
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich if (num_setzones > 1) {
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich (void) fprintf(stderr,
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich "Only one of -G and -z may be set\n");
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich return (-1);
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich }
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich if (ipzo.ipfz_gz == 1 &&
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich getzoneidbyname(ipzo.ipfz_zonename) == GLOBAL_ZONEID) {
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich (void) fprintf(stderr,
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich "-G cannot be used with the global zone\n");
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich return (-1);
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich }
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich if (ioctl(fd, SIOCIPFZONESET, &ipzo) == -1) {
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich switch (errno) {
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich case ENODEV:
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich (void) fprintf(stderr,
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich "Could not find running zone: %s\n",
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich ipzo.ipfz_zonename);
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich break;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich case EACCES:
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich (void) fprintf(stderr,
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich "Permission denied setting zone: %s\n",
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich ipzo.ipfz_zonename);
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich break;
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich default:
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich perror("Error setting zone");
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich }
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich return (-1);
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich }
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich return (0);
94bdecd9e84ae1042607002db3e64a6849da5874Rob Gulewich}