1*94bdecd9SRob Gulewich /* 2*94bdecd9SRob Gulewich * Copyright (c) 2014 Joyent, Inc. All rights reserved. 3*94bdecd9SRob Gulewich * Use is subject to license terms. 4*94bdecd9SRob Gulewich * 5*94bdecd9SRob Gulewich * See the IPFILTER.LICENCE file for details on licensing. 6*94bdecd9SRob Gulewich */ 7*94bdecd9SRob Gulewich 8*94bdecd9SRob Gulewich 9*94bdecd9SRob Gulewich #include <errno.h> 10*94bdecd9SRob Gulewich #include <net/if.h> 11*94bdecd9SRob Gulewich #include <stdio.h> 12*94bdecd9SRob Gulewich #include <string.h> 13*94bdecd9SRob Gulewich #include <unistd.h> 14*94bdecd9SRob Gulewich #include <zone.h> 15*94bdecd9SRob Gulewich 16*94bdecd9SRob Gulewich #include "netinet/ip_fil.h" 17*94bdecd9SRob Gulewich #include "ipfzone.h" 18*94bdecd9SRob Gulewich 19*94bdecd9SRob Gulewich static ipfzoneobj_t ipzo; 20*94bdecd9SRob Gulewich static boolean_t do_setzone = 0; 21*94bdecd9SRob Gulewich static int num_setzones = 0; 22*94bdecd9SRob Gulewich 23*94bdecd9SRob Gulewich extern int errno; 24*94bdecd9SRob Gulewich extern int opterr; 25*94bdecd9SRob Gulewich extern int optind; 26*94bdecd9SRob Gulewich extern char *optarg; 27*94bdecd9SRob Gulewich 28*94bdecd9SRob Gulewich /* 29*94bdecd9SRob Gulewich * Get the zonename if it's the last argument and set the zonename 30*94bdecd9SRob Gulewich * in ipfzo to it. This is used by ipf(1m) only - all of the other tools 31*94bdecd9SRob Gulewich * specify the zone with the -z option, and therefore use getzoneopt() below. 32*94bdecd9SRob Gulewich */ 33*94bdecd9SRob Gulewich void 34*94bdecd9SRob Gulewich getzonearg(int argc, char *argv[], const char *optstr) 35*94bdecd9SRob Gulewich { 36*94bdecd9SRob Gulewich int c; 37*94bdecd9SRob Gulewich 38*94bdecd9SRob Gulewich /* 39*94bdecd9SRob Gulewich * Don't warn about unknown options - let subsequent calls to 40*94bdecd9SRob Gulewich * getopt() handle this. 41*94bdecd9SRob Gulewich */ 42*94bdecd9SRob Gulewich opterr = 0; 43*94bdecd9SRob Gulewich 44*94bdecd9SRob Gulewich /* 45*94bdecd9SRob Gulewich * getopt is also used here to set optind so that we can 46*94bdecd9SRob Gulewich * determine if the last argument belongs to a flag or is 47*94bdecd9SRob Gulewich * actually a zonename. 48*94bdecd9SRob Gulewich */ 49*94bdecd9SRob Gulewich while ((c = getopt(argc, argv, optstr)) != -1) { 50*94bdecd9SRob Gulewich if (c == 'G') 51*94bdecd9SRob Gulewich ipzo.ipfz_gz = 1; 52*94bdecd9SRob Gulewich } 53*94bdecd9SRob Gulewich 54*94bdecd9SRob Gulewich if (optind < argc) 55*94bdecd9SRob Gulewich setzonename(argv[optind]); 56*94bdecd9SRob Gulewich 57*94bdecd9SRob Gulewich /* 58*94bdecd9SRob Gulewich * Reset optind and opterr so the next getopt call will go through all 59*94bdecd9SRob Gulewich * of argv again and warn about unknown options. 60*94bdecd9SRob Gulewich */ 61*94bdecd9SRob Gulewich optind = 1; 62*94bdecd9SRob Gulewich opterr = 1; 63*94bdecd9SRob Gulewich } 64*94bdecd9SRob Gulewich 65*94bdecd9SRob Gulewich /* 66*94bdecd9SRob Gulewich * Get a -z option from argv and set the zonename in ipfzo accordingly 67*94bdecd9SRob Gulewich */ 68*94bdecd9SRob Gulewich void 69*94bdecd9SRob Gulewich getzoneopt(int argc, char *argv[], const char *optstr) 70*94bdecd9SRob Gulewich { 71*94bdecd9SRob Gulewich int c; 72*94bdecd9SRob Gulewich 73*94bdecd9SRob Gulewich /* 74*94bdecd9SRob Gulewich * Don't warn about unknown options - let subsequent calls to 75*94bdecd9SRob Gulewich * getopt() handle this. 76*94bdecd9SRob Gulewich */ 77*94bdecd9SRob Gulewich opterr = 0; 78*94bdecd9SRob Gulewich 79*94bdecd9SRob Gulewich while ((c = getopt(argc, argv, optstr)) != -1) { 80*94bdecd9SRob Gulewich if (c == 'G') 81*94bdecd9SRob Gulewich setzonename_global(optarg); 82*94bdecd9SRob Gulewich 83*94bdecd9SRob Gulewich if (c == 'z') 84*94bdecd9SRob Gulewich setzonename(optarg); 85*94bdecd9SRob Gulewich } 86*94bdecd9SRob Gulewich 87*94bdecd9SRob Gulewich /* 88*94bdecd9SRob Gulewich * Reset optind and opterr so the next getopt call will go through all 89*94bdecd9SRob Gulewich * of argv again and warn about unknown options. 90*94bdecd9SRob Gulewich */ 91*94bdecd9SRob Gulewich optind = 1; 92*94bdecd9SRob Gulewich opterr = 1; 93*94bdecd9SRob Gulewich } 94*94bdecd9SRob Gulewich 95*94bdecd9SRob Gulewich /* 96*94bdecd9SRob Gulewich * Set the zonename in ipfzo to the given string: this is the zone all further 97*94bdecd9SRob Gulewich * ioctls will act on. 98*94bdecd9SRob Gulewich */ 99*94bdecd9SRob Gulewich void 100*94bdecd9SRob Gulewich setzonename(const char *zonename) 101*94bdecd9SRob Gulewich { 102*94bdecd9SRob Gulewich memcpy(ipzo.ipfz_zonename, zonename, sizeof (ipzo.ipfz_zonename)); 103*94bdecd9SRob Gulewich do_setzone = B_TRUE; 104*94bdecd9SRob Gulewich num_setzones++; 105*94bdecd9SRob Gulewich } 106*94bdecd9SRob Gulewich 107*94bdecd9SRob Gulewich /* 108*94bdecd9SRob Gulewich * Set the zonename in ipfo, and the gz flag. This indicates that we want all 109*94bdecd9SRob Gulewich * further ioctls to act on the GZ-controlled stack for that zone. 110*94bdecd9SRob Gulewich */ 111*94bdecd9SRob Gulewich void 112*94bdecd9SRob Gulewich setzonename_global(const char *zonename) 113*94bdecd9SRob Gulewich { 114*94bdecd9SRob Gulewich setzonename(zonename); 115*94bdecd9SRob Gulewich ipzo.ipfz_gz = 1; 116*94bdecd9SRob Gulewich } 117*94bdecd9SRob Gulewich 118*94bdecd9SRob Gulewich /* 119*94bdecd9SRob Gulewich * Set the zone that all further ioctls will operate on. See the "GZ-controlled 120*94bdecd9SRob Gulewich * and per-zone stacks" note at the top of ip_fil_solaris.c for further 121*94bdecd9SRob Gulewich * explanation. 122*94bdecd9SRob Gulewich */ 123*94bdecd9SRob Gulewich int 124*94bdecd9SRob Gulewich setzone(int fd) 125*94bdecd9SRob Gulewich { 126*94bdecd9SRob Gulewich if (!do_setzone) 127*94bdecd9SRob Gulewich return (0); 128*94bdecd9SRob Gulewich 129*94bdecd9SRob Gulewich if (num_setzones > 1) { 130*94bdecd9SRob Gulewich (void) fprintf(stderr, 131*94bdecd9SRob Gulewich "Only one of -G and -z may be set\n"); 132*94bdecd9SRob Gulewich return (-1); 133*94bdecd9SRob Gulewich } 134*94bdecd9SRob Gulewich 135*94bdecd9SRob Gulewich if (ipzo.ipfz_gz == 1 && 136*94bdecd9SRob Gulewich getzoneidbyname(ipzo.ipfz_zonename) == GLOBAL_ZONEID) { 137*94bdecd9SRob Gulewich (void) fprintf(stderr, 138*94bdecd9SRob Gulewich "-G cannot be used with the global zone\n"); 139*94bdecd9SRob Gulewich return (-1); 140*94bdecd9SRob Gulewich } 141*94bdecd9SRob Gulewich 142*94bdecd9SRob Gulewich if (ioctl(fd, SIOCIPFZONESET, &ipzo) == -1) { 143*94bdecd9SRob Gulewich switch (errno) { 144*94bdecd9SRob Gulewich case ENODEV: 145*94bdecd9SRob Gulewich (void) fprintf(stderr, 146*94bdecd9SRob Gulewich "Could not find running zone: %s\n", 147*94bdecd9SRob Gulewich ipzo.ipfz_zonename); 148*94bdecd9SRob Gulewich break; 149*94bdecd9SRob Gulewich case EACCES: 150*94bdecd9SRob Gulewich (void) fprintf(stderr, 151*94bdecd9SRob Gulewich "Permission denied setting zone: %s\n", 152*94bdecd9SRob Gulewich ipzo.ipfz_zonename); 153*94bdecd9SRob Gulewich break; 154*94bdecd9SRob Gulewich default: 155*94bdecd9SRob Gulewich perror("Error setting zone"); 156*94bdecd9SRob Gulewich } 157*94bdecd9SRob Gulewich return (-1); 158*94bdecd9SRob Gulewich } 159*94bdecd9SRob Gulewich 160*94bdecd9SRob Gulewich return (0); 161*94bdecd9SRob Gulewich } 162