+ long ret;
+ int permit = -1, state = 0;
+ int perm = -1, args = 0, flags = 0;
+ struct vx_info *vxi = NULL;
+ struct nx_info *nxi = NULL;
+
+ switch (cmd) {
+ /* unpriviledged commands */
+ __VCMD(get_version, 0, VCA_NONE, 0);
+ __VCMD(get_vci, 0, VCA_NONE, 0);
+ __VCMD(get_rlimit_mask, 0, VCA_NONE, 0);
+ __VCMD(get_space_mask, 0, VCA_NONE, 0);
+
+ /* info commands */
+ __VCMD(task_xid, 2, VCA_NONE, 0);
+ __VCMD(reset_minmax, 2, VCA_VXI, 0);
+ __VCMD(vx_info, 3, VCA_VXI, VCF_INFO);
+ __VCMD(get_bcaps, 3, VCA_VXI, VCF_INFO);
+ __VCMD(get_ccaps_v0, 3, VCA_VXI, VCF_INFO);
+ __VCMD(get_ccaps, 3, VCA_VXI, VCF_INFO);
+ __VCMD(get_cflags, 3, VCA_VXI, VCF_INFO);
+ __VCMD(get_vhi_name, 3, VCA_VXI, VCF_INFO);
+ __VCMD(get_rlimit, 3, VCA_VXI, VCF_INFO);
+
+ __VCMD(ctx_stat, 3, VCA_VXI, VCF_INFO);
+ __VCMD(virt_stat, 3, VCA_VXI, VCF_INFO);
+ __VCMD(sock_stat, 3, VCA_VXI, VCF_INFO);
+ __VCMD(rlimit_stat, 3, VCA_VXI, VCF_INFO);
+
+ __VCMD(task_nid, 2, VCA_NONE, 0);
+ __VCMD(nx_info, 3, VCA_NXI, VCF_INFO);
+ __VCMD(get_ncaps, 3, VCA_NXI, VCF_INFO);
+ __VCMD(get_nflags, 3, VCA_NXI, VCF_INFO);
+
+ __VCMD(get_iattr, 2, VCA_NONE, 0);
+ __VCMD(get_dlimit, 3, VCA_NONE, VCF_INFO);
+ __VCMD(get_sched, 3, VCA_VXI, VCF_INFO);
+ __VCMD(sched_info, 3, VCA_VXI, VCF_INFO|VCF_ZIDOK);
+
+ /* lower admin commands */
+ __VCMD(wait_exit, 4, VCA_VXI, VCF_INFO);
+ __VCMD(ctx_create_v0, 5, VCA_NONE, 0);
+ __VCMD(ctx_create, 5, VCA_NONE, 0);
+ __VCMD(ctx_migrate_v0, 5, VCA_VXI, VCF_ADMIN);
+ __VCMD(ctx_migrate, 5, VCA_VXI, VCF_ADMIN);
+ __VCMD(enter_space_v0, 5, VCA_VXI, VCF_ADMIN);
+ __VCMD(enter_space, 5, VCA_VXI, VCF_ADMIN);
+
+ __VCMD(net_create_v0, 5, VCA_NONE, 0);
+ __VCMD(net_create, 5, VCA_NONE, 0);
+ __VCMD(net_migrate, 5, VCA_NXI, VCF_ADMIN);
+
+ /* higher admin commands */
+ __VCMD(ctx_kill, 6, VCA_VXI, VCF_ARES);
+ __VCMD(set_space_v0, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
+ __VCMD(set_space, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
+
+ __VCMD(set_ccaps_v0, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
+ __VCMD(set_ccaps, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
+ __VCMD(set_bcaps, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
+ __VCMD(set_cflags, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
+
+ __VCMD(set_vhi_name, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
+ __VCMD(set_rlimit, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
+ __VCMD(set_sched, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
+ __VCMD(set_sched_v2, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
+ __VCMD(set_sched_v3, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
+ __VCMD(set_sched_v4, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
+
+ __VCMD(set_ncaps, 7, VCA_NXI, VCF_ARES|VCF_SETUP);
+ __VCMD(set_nflags, 7, VCA_NXI, VCF_ARES|VCF_SETUP);
+ __VCMD(net_add, 8, VCA_NXI, VCF_ARES|VCF_SETUP);
+ __VCMD(net_remove, 8, VCA_NXI, VCF_ARES|VCF_SETUP);
+
+ __VCMD(set_iattr, 7, VCA_NONE, 0);
+ __VCMD(set_dlimit, 7, VCA_NONE, VCF_ARES);
+ __VCMD(add_dlimit, 8, VCA_NONE, VCF_ARES);
+ __VCMD(rem_dlimit, 8, VCA_NONE, VCF_ARES);
+
+ /* debug level admin commands */
+#ifdef CONFIG_VSERVER_HISTORY
+ __VCMD(dump_history, 9, VCA_NONE, 0);
+ __VCMD(read_history, 9, VCA_NONE, 0);
+#endif
+#ifdef CONFIG_VSERVER_MONITOR
+ __VCMD(read_monitor, 9, VCA_NONE, 0);
+#endif
+
+ /* legacy commands */
+#ifdef CONFIG_VSERVER_LEGACY
+ __VCMD(new_s_context, 1, VCA_NONE, 0);
+ __VCMD(create_context, 5, VCA_NONE, 0);
+#endif
+#ifdef CONFIG_VSERVER_LEGACYNET
+ __VCMD(set_ipv4root, 5, VCA_NONE, 0);
+#endif
+ default:
+ perm = -1;
+ }
+
+ vxdprintk(VXD_CBIT(switch, 0),
+ "vc: VCMD_%02d_%d[%d], %d,%p [%d,%d,%x,%x]",
+ VC_CATEGORY(cmd), VC_COMMAND(cmd),
+ VC_VERSION(cmd), id, data, compat,
+ perm, args, flags);
+
+ ret = -ENOSYS;
+ if (perm < 0)
+ goto out;
+
+ state = 1;
+#ifdef CONFIG_VSERVER_LEGACY
+ if (!capable(CAP_CONTEXT) &&
+ /* dirty hack for capremove */
+ !(cmd==VCMD_new_s_context && id==-2))
+ goto out;
+#else
+ if (!capable(CAP_CONTEXT))
+ goto out;
+#endif
+
+ state = 2;
+ /* moved here from the individual commands */
+ ret = -EPERM;
+ if ((perm > 1) && !capable(CAP_SYS_ADMIN))
+ goto out;
+
+ state = 3;
+ /* vcmd involves resource management */
+ ret = -EPERM;
+ if ((flags & VCF_ARES) && !capable(CAP_SYS_RESOURCE))
+ goto out;