Add support for the unshare mask
[util-vserver.git] / src / vattribute.c
1 // $Id$    --*- c -*--
2
3 // Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 //  
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; version 2 of the License.
8 //  
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //  
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18
19 #ifdef HAVE_CONFIG_H
20 #  include <config.h>
21 #endif
22
23 #include "util.h"
24 #include "attribute-util.h"
25 #include <lib/vserver.h>
26
27 #include <getopt.h>
28 #include <stdint.h>
29 #include <errno.h>
30
31 #define ENSC_WRAPPERS_PREFIX    "vattribute: "
32 #define ENSC_WRAPPERS_VSERVER   1
33 #define ENSC_WRAPPERS_UNISTD    1
34 #include <wrappers.h>
35
36 #define CMD_HELP                0x1000
37 #define CMD_VERSION             0x1001
38 #define CMD_XID                 0x2000
39 #define CMD_SET                 0x2001
40 #define CMD_CCAP                0x2002
41 #define CMD_FLAG                0x2003
42 #define CMD_SECURE              0x2004
43 #define CMD_BCAP                0x2005
44 #define CMD_GET                 0x2006
45 #define CMD_UMASK               0x2007
46
47 int                     wrapper_exit_code = 1;
48
49 struct option const
50 CMDLINE_OPTIONS[] = {
51   { "help",       no_argument,       0, CMD_HELP },
52   { "version",    no_argument,       0, CMD_VERSION },
53   { "xid",        required_argument, 0, CMD_XID },
54   { "set",        no_argument,       0, CMD_SET },
55   { "get",        no_argument,       0, CMD_GET },
56   { "ccap",       required_argument, 0, CMD_CCAP },
57   { "bcap",       required_argument, 0, CMD_BCAP },
58   { "flag",       required_argument, 0, CMD_FLAG },
59   { "secure",     no_argument,       0, CMD_SECURE },
60   { "umask",      required_argument, 0, CMD_UMASK },
61   {0,0,0,0}
62 };
63
64 struct Arguments {
65     xid_t               xid;
66     struct vc_ctx_flags flags;
67     struct vc_ctx_caps  caps;
68     struct vc_umask     umask;
69     int                 mode;
70 };
71
72 static void
73 showHelp(int fd, char const *cmd, int res)
74 {
75   WRITE_MSG(fd, "Usage:\n    ");
76   WRITE_STR(fd, cmd);
77   WRITE_MSG(fd,
78             " [--xid <xid>] {--get|--set [--bcap [~!]<cap>] [--ccap [~!]<cap>]\n"
79             "    [--flag [~!]<flag>] [--secure]} -- [<program> <args>*]\n"
80             "\n"
81             " --bcap <cap>   ...  system  capability to be set\n"
82             " --ccap <cap>   ...  context capability to be set\n"
83             " --flag <flag>  ...  context flag to be set\n"
84             " --umask <mask> ...  unshare mask to be set\n"
85             "\n"
86             "Please report bugs to " PACKAGE_BUGREPORT "\n");
87
88   exit(res);
89 }
90
91 static void
92 showVersion()
93 {
94   WRITE_MSG(1,
95             "vattribute " VERSION " -- sets/gets attributes of vservers\n"
96             "This program is part of " PACKAGE_STRING "\n\n"
97             "Copyright (C) 2004 Enrico Scholz\n"
98             VERSION_COPYRIGHT_DISCLAIMER);
99   exit(0);
100 }
101
102 static void
103 parseFlags(char const *str, struct vc_ctx_flags *flags)
104 {
105   struct vc_err_listparser      err;
106   int                           rc;
107
108   rc = vc_list2cflag(str,0, &err, flags);
109   
110   if (rc==-1) {
111     WRITE_MSG(2, "Unknown flag '");
112     Vwrite(2, err.ptr, err.len);
113     WRITE_MSG(2, "'\n");
114     exit(wrapper_exit_code);
115   }
116 }
117
118 static void
119 parseBCaps(char const *str, struct vc_ctx_caps *caps)
120 {
121   struct vc_err_listparser      err;
122   int                           rc;
123
124   rc = vc_list2bcap(str,0, &err, caps);
125   
126   if (rc==-1) {
127     WRITE_MSG(2, "Unknown bcap '");
128     Vwrite(2, err.ptr, err.len);
129     WRITE_MSG(2, "'\n");
130     exit(wrapper_exit_code);
131   }
132 }
133
134 static void
135 parseCCaps(char const *str, struct vc_ctx_caps *caps)
136 {
137   struct vc_err_listparser      err;
138   int                           rc;
139
140   rc = vc_list2ccap(str,0, &err, caps);
141   
142   if (rc==-1) {
143     WRITE_MSG(2, "Unknown ccap '");
144     Vwrite(2, err.ptr, err.len);
145     WRITE_MSG(2, "'\n");
146     exit(wrapper_exit_code);
147   }
148 }
149
150 static void
151 parseUMask(char const *str, struct vc_umask *umask)
152 {
153   struct vc_err_listparser      err;
154   int                           rc;
155
156   rc = vc_list2umask(str, 0, &err, umask);
157   
158   if (rc==-1) {
159     WRITE_MSG(2, "Unknown namespace '");
160     Vwrite(2, err.ptr, err.len);
161     WRITE_MSG(2, "'\n");
162     exit(wrapper_exit_code);
163   }
164 }
165
166 static void
167 parseSecure(struct vc_ctx_flags UNUSED * flags,
168             struct vc_ctx_caps  UNUSED * caps)
169 {
170   caps->ccaps = ~vc_get_insecureccaps();
171   caps->cmask = ~0ull;
172   caps->bcaps = ~vc_get_insecurebcaps();
173   caps->bmask = ~0ull;
174
175     // TODO: generalize this
176   flags->flagword = VC_VXF_HIDE_NETIF;
177   flags->mask     = VC_VXF_HIDE_NETIF;
178 }
179
180 static int
181 printAttrs(struct Arguments *args)
182 {
183   struct vc_ctx_flags flags;
184   struct vc_ctx_caps caps;
185   struct vc_umask umask = { .mask = ~0, .umask = 0x20200 };
186
187   Evc_get_cflags(args->xid, &flags);
188   Evc_get_ccaps(args->xid, &caps);
189   Evc_get_umask(args->xid, &umask);
190
191   print_bitfield(1, bcap, "bcapabilities", &caps.bcaps);
192   print_bitfield(1, ccap, "ccapabilities", &caps.ccaps);
193   print_bitfield(1, cflag, "flags", &flags.flagword);
194   print_bitfield(1, umask, "umask", &umask.umask);
195
196   return 0;
197 }
198
199 int main(int argc, char *argv[])
200 {
201   struct Arguments              args = {
202     .xid   = VC_NOCTX,
203     .flags = { .flagword = 0, .mask = 0 },
204     .caps  = { .bcaps = 0, .bmask = 0,.ccaps = 0, .cmask = 0 },
205     .umask = { .umask = 0, .mask = 0 },
206     .mode  = CMD_SET,
207   };
208
209   while (1) {
210     int         c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0);
211     if (c==-1) break;
212
213     switch (c) {
214       case CMD_HELP     :  showHelp(1, argv[0], 0);
215       case CMD_VERSION  :  showVersion();
216       case CMD_SET      :  args.mode = CMD_SET;                    break;
217       case CMD_GET      :  args.mode = CMD_GET;                    break;
218       case CMD_XID      :  args.xid = Evc_xidopt2xid(optarg,true); break;
219       case CMD_FLAG     :  parseFlags(optarg, &args.flags);        break;
220       case CMD_CCAP     :  parseCCaps(optarg, &args.caps);         break;
221       case CMD_BCAP     :  parseBCaps(optarg, &args.caps);         break;
222       case CMD_SECURE   :  parseSecure(&args.flags, &args.caps);   break;
223       case CMD_UMASK    :  parseUMask(optarg, &args.umask);        break;
224       default           :
225         WRITE_MSG(2, "Try '");
226         WRITE_STR(2, argv[0]);
227         WRITE_MSG(2, " --help' for more information.\n");
228         return 255;
229         break;
230     }
231   }
232
233   if (args.xid==VC_NOCTX) args.xid = Evc_get_task_xid(0);
234
235   if (args.mode == CMD_SET) {
236     if ((args.caps.cmask || args.caps.bmask) &&
237         vc_set_ccaps(args.xid, &args.caps)==-1)
238       perror(ENSC_WRAPPERS_PREFIX "vc_set_ccaps()");
239     else if (args.flags.mask &&
240              vc_set_cflags(args.xid, &args.flags)==-1)
241       perror(ENSC_WRAPPERS_PREFIX "vc_set_flags()");
242     else if (args.umask.mask &&
243              vc_set_umask(args.xid, &args.umask)==-1)
244       perror(ENSC_WRAPPERS_PREFIX "vc_set_umask()");
245     else if (optind<argc)
246       EexecvpD(argv[optind], argv+optind);
247     else
248       return EXIT_SUCCESS;
249   }
250   else if (args.mode == CMD_GET) {
251     printAttrs(&args);
252     if (optind<argc)
253       EexecvpD(argv[optind], argv+optind);
254     else
255       return EXIT_SUCCESS;
256   }
257
258   return EXIT_FAILURE;
259 }