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
getzonearg(int argc,char * argv[],const char * optstr)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
getzoneopt(int argc,char * argv[],const char * optstr)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
setzonename(const char * zonename)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
setzonename_global(const char * zonename)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
setzone(int fd)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