Add support for PID and net namespaces.
[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 <lib/vserver.h>
25
26 #include <getopt.h>
27 #include <stdint.h>
28 #include <errno.h>
29
30 #define ENSC_WRAPPERS_PREFIX    "vattribute: "
31 #define ENSC_WRAPPERS_VSERVER   1
32 #define ENSC_WRAPPERS_UNISTD    1
33 #include <wrappers.h>
34
35 #define CMD_HELP                0x1000
36 #define CMD_VERSION             0x1001
37 #define CMD_XID                 0x2000
38 #define CMD_SET                 0x2001
39 #define CMD_CCAP                0x2002
40 #define CMD_FLAG                0x2003
41 #define CMD_SECURE              0x2004
42 #define CMD_BCAP                0x2005
43 #define CMD_GET                 0x2006
44
45 int                     wrapper_exit_code = 1;
46
47 struct option const
48 CMDLINE_OPTIONS[] = {
49   { "help",       no_argument,       0, CMD_HELP },
50   { "version",    no_argument,       0, CMD_VERSION },
51   { "xid",        required_argument, 0, CMD_XID },
52   { "set",        no_argument,       0, CMD_SET },
53   { "get",        no_argument,       0, CMD_GET },
54   { "ccap",       required_argument, 0, CMD_CCAP },
55   { "bcap",       required_argument, 0, CMD_BCAP },
56   { "flag",       required_argument, 0, CMD_FLAG },
57   { "secure",     no_argument,       0, CMD_SECURE },
58   {0,0,0,0}
59 };
60
61 struct Arguments {
62     xid_t               xid;
63     struct vc_ctx_flags flags;
64     struct vc_ctx_caps  caps;
65     int                 mode;
66 };
67
68 static void
69 showHelp(int fd, char const *cmd, int res)
70 {
71   WRITE_MSG(fd, "Usage:\n    ");
72   WRITE_STR(fd, cmd);
73   WRITE_MSG(fd,
74             " [--xid <xid>] {--get|--set [--bcap [~!]<cap>] [--ccap [~!]<cap>]\n"
75             "    [--flag [~!]<flag>] [--secure]} -- [<program> <args>*]\n"
76             "\n"
77             " --bcap <cap>   ...  system  capability to be set\n"
78             " --ccap <cap>   ...  context capability to be set\n"
79             " --flag <flag>  ...  context flag to be set\n"
80             "\n"
81             "Please report bugs to " PACKAGE_BUGREPORT "\n");
82
83   exit(res);
84 }
85
86 static void
87 showVersion()
88 {
89   WRITE_MSG(1,
90             "vattribute " VERSION " -- sets/gets attributes of vservers\n"
91             "This program is part of " PACKAGE_STRING "\n\n"
92             "Copyright (C) 2004 Enrico Scholz\n"
93             VERSION_COPYRIGHT_DISCLAIMER);
94   exit(0);
95 }
96
97 static void
98 parseFlags(char const *str, struct vc_ctx_flags *flags)
99 {
100   struct vc_err_listparser      err;
101   int                           rc;
102
103   rc = vc_list2cflag(str,0, &err, flags);
104   
105   if (rc==-1) {
106     WRITE_MSG(2, "Unknown flag '");
107     Vwrite(2, err.ptr, err.len);
108     WRITE_MSG(2, "'\n");
109     exit(wrapper_exit_code);
110   }
111 }
112
113 static void
114 parseBCaps(char const *str, struct vc_ctx_caps *caps)
115 {
116   struct vc_err_listparser      err;
117   int                           rc;
118
119   rc = vc_list2bcap(str,0, &err, caps);
120   
121   if (rc==-1) {
122     WRITE_MSG(2, "Unknown bcap '");
123     Vwrite(2, err.ptr, err.len);
124     WRITE_MSG(2, "'\n");
125     exit(wrapper_exit_code);
126   }
127 }
128
129 static void
130 parseCCaps(char const *str, struct vc_ctx_caps *caps)
131 {
132   struct vc_err_listparser      err;
133   int                           rc;
134
135   rc = vc_list2ccap(str,0, &err, caps);
136   
137   if (rc==-1) {
138     WRITE_MSG(2, "Unknown ccap '");
139     Vwrite(2, err.ptr, err.len);
140     WRITE_MSG(2, "'\n");
141     exit(wrapper_exit_code);
142   }
143 }
144
145 static void
146 parseSecure(struct vc_ctx_flags UNUSED * flags,
147             struct vc_ctx_caps  UNUSED * caps)
148 {
149   caps->ccaps = ~vc_get_insecureccaps();
150   caps->cmask = ~0ull;
151   caps->bcaps = ~vc_get_insecurebcaps();
152   caps->bmask = ~0ull;
153
154     // TODO: generalize this
155   flags->flagword = VC_VXF_HIDE_NETIF;
156   flags->mask     = VC_VXF_HIDE_NETIF;
157 }
158
159 static inline int
160 ffsull(unsigned long long word)
161 {
162   int bit;
163   for (bit = 0; bit < 64; bit++) {
164     if (word & (1ULL << bit))
165       break;
166   }
167   if (bit == 64)
168     bit = 0;
169   return bit;
170 }
171
172 static int
173 printAttrs(struct Arguments *args)
174 {
175   struct vc_ctx_flags flags;
176   struct vc_ctx_caps caps;
177   int first;
178
179   Evc_get_cflags(args->xid, &flags);
180   Evc_get_ccaps(args->xid, &caps);
181
182 #define PRINT_VALUES(type, name, var)   \
183   WRITE_MSG(1, name ":\n");             \
184   first = 1;                            \
185   while (1) {                           \
186     char const *i;                      \
187     i = vc_lo ## type ## 2text(var);    \
188     if (!i)                             \
189       break;                            \
190     if (!first)                         \
191       WRITE_MSG(1, ",");                \
192     else                                \
193       first = 0;                        \
194     WRITE_STR(1, i);                    \
195   }                                     \
196   while (*(var)) {                      \
197     int bit = ffsull(*(var));           \
198     if (!bit)                           \
199       break;                            \
200     if (!first)                         \
201       WRITE_MSG(1, ",");                \
202     else                                \
203       first = 0;                        \
204     WRITE_MSG(1, "^");                  \
205     WRITE_INT(1, bit);                  \
206     *(var) &= ~(1ULL << bit);           \
207   }                                     \
208   WRITE_MSG(1, "\n");
209
210   PRINT_VALUES(bcap, "bcapabilities", &caps.bcaps);
211   PRINT_VALUES(ccap, "ccapabilities", &caps.ccaps);
212   PRINT_VALUES(cflag, "flags", &flags.flagword);
213
214   return 0;
215 }
216
217 int main(int argc, char *argv[])
218 {
219   struct Arguments              args = {
220     .xid   = VC_NOCTX,
221     .flags = { .flagword = 0, .mask = 0 },
222     .caps  = { .bcaps = 0, .bmask = 0,.ccaps = 0, .cmask = 0 },
223     .mode  = CMD_SET,
224   };
225
226   while (1) {
227     int         c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0);
228     if (c==-1) break;
229
230     switch (c) {
231       case CMD_HELP     :  showHelp(1, argv[0], 0);
232       case CMD_VERSION  :  showVersion();
233       case CMD_SET      :  args.mode = CMD_SET;                    break;
234       case CMD_GET      :  args.mode = CMD_GET;                    break;
235       case CMD_XID      :  args.xid = Evc_xidopt2xid(optarg,true); break;
236       case CMD_FLAG     :  parseFlags(optarg, &args.flags);        break;
237       case CMD_CCAP     :  parseCCaps(optarg, &args.caps);         break;
238       case CMD_BCAP     :  parseBCaps(optarg, &args.caps);         break;
239       case CMD_SECURE   :  parseSecure(&args.flags, &args.caps);   break;
240       default           :
241         WRITE_MSG(2, "Try '");
242         WRITE_STR(2, argv[0]);
243         WRITE_MSG(2, " --help' for more information.\n");
244         return 255;
245         break;
246     }
247   }
248
249   if (args.xid==VC_NOCTX) args.xid = Evc_get_task_xid(0);
250
251   if (args.mode == CMD_SET) {
252     if ((args.caps.cmask || args.caps.bmask) &&
253         vc_set_ccaps(args.xid, &args.caps)==-1)
254       perror(ENSC_WRAPPERS_PREFIX "vc_set_ccaps()");
255     else if (args.flags.mask &&
256              vc_set_cflags(args.xid, &args.flags)==-1)
257       perror(ENSC_WRAPPERS_PREFIX "vc_set_flags()");
258     else if (optind<argc)
259       EexecvpD(argv[optind], argv+optind);
260     else
261       return EXIT_SUCCESS;
262   }
263   else if (args.mode == CMD_GET) {
264     printAttrs(&args);
265     if (optind<argc)
266       EexecvpD(argv[optind], argv+optind);
267     else
268       return EXIT_SUCCESS;
269   }
270
271   return EXIT_FAILURE;
272 }