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