vserver 2.0 rc7
[linux-2.6.git] / kernel / vserver / helper.c
1 /*
2  *  linux/kernel/vserver/helper.c
3  *
4  *  Virtual Context Support
5  *
6  *  Copyright (C) 2004-2005  Herbert Pƶtzl
7  *
8  *  V0.01  basic helper
9  *
10  */
11
12 #include <linux/config.h>
13 #include <linux/errno.h>
14 #include <linux/reboot.h>
15 #include <linux/kmod.h>
16 #include <linux/sched.h>
17 #include <linux/vs_context.h>
18 #include <linux/vs_network.h>
19
20 #include <asm/uaccess.h>
21 #include <asm/unistd.h>
22
23
24 char vshelper_path[255] = "/sbin/vshelper";
25
26
27 int do_vshelper(char *name, char *argv[], char *envp[], int sync)
28 {
29         int ret;
30
31         if ((ret = call_usermodehelper(name, argv, envp, sync))) {
32                 printk( KERN_WARNING
33                         "%s: (%s %s) returned %s with %d\n",
34                         name, argv[1], argv[2],
35                         sync?"sync":"async", ret);
36         }
37         vxdprintk(VXD_CBIT(switch, 4),
38                 "%s: (%s %s) returned %s with %d",
39                 name, argv[1], argv[2], sync?"sync":"async", ret);
40         return ret;
41 }
42
43 /*
44  *      vshelper path is set via /proc/sys
45  *      invoked by vserver sys_reboot(), with
46  *      the following arguments
47  *
48  *      argv [0] = vshelper_path;
49  *      argv [1] = action: "restart", "halt", "poweroff", ...
50  *      argv [2] = context identifier
51  *
52  *      envp [*] = type-specific parameters
53  */
54
55 long vs_reboot(unsigned int cmd, void * arg)
56 {
57         char id_buf[8], cmd_buf[16];
58         char uid_buf[16], pid_buf[16];
59         int ret;
60
61         char *argv[] = {vshelper_path, NULL, id_buf, 0};
62         char *envp[] = {"HOME=/", "TERM=linux",
63                         "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
64                         uid_buf, pid_buf, cmd_buf, 0};
65
66         snprintf(id_buf, sizeof(id_buf)-1, "%d", vx_current_xid());
67
68         snprintf(cmd_buf, sizeof(cmd_buf)-1, "VS_CMD=%08x", cmd);
69         snprintf(uid_buf, sizeof(uid_buf)-1, "VS_UID=%d", current->uid);
70         snprintf(pid_buf, sizeof(pid_buf)-1, "VS_PID=%d", current->pid);
71
72         switch (cmd) {
73         case LINUX_REBOOT_CMD_RESTART:
74                 argv[1] = "restart";
75                 break;
76
77         case LINUX_REBOOT_CMD_HALT:
78                 argv[1] = "halt";
79                 break;
80
81         case LINUX_REBOOT_CMD_POWER_OFF:
82                 argv[1] = "poweroff";
83                 break;
84
85         case LINUX_REBOOT_CMD_SW_SUSPEND:
86                 argv[1] = "swsusp";
87                 break;
88
89         default:
90                 return 0;
91         }
92
93 #ifndef CONFIG_VSERVER_LEGACY
94         ret = do_vshelper(vshelper_path, argv, envp, 1);
95 #else
96         ret = do_vshelper(vshelper_path, argv, envp, 0);
97 #endif
98         return (ret) ? -EPERM : 0;
99 }
100
101
102 /*
103  *      argv [0] = vshelper_path;
104  *      argv [1] = action: "startup", "shutdown"
105  *      argv [2] = context identifier
106  *
107  *      envp [*] = type-specific parameters
108  */
109
110 long vs_state_change(struct vx_info *vxi, unsigned int cmd)
111 {
112         char id_buf[8], cmd_buf[16];
113         char *argv[] = {vshelper_path, NULL, id_buf, 0};
114         char *envp[] = {"HOME=/", "TERM=linux",
115                         "PATH=/sbin:/usr/sbin:/bin:/usr/bin", cmd_buf, 0};
116
117         if (!vx_info_flags(vxi, VXF_STATE_HELPER, 0))
118                 return 0;
119
120         snprintf(id_buf, sizeof(id_buf)-1, "%d", vxi->vx_id);
121         snprintf(cmd_buf, sizeof(cmd_buf)-1, "VS_CMD=%08x", cmd);
122
123         switch (cmd) {
124         case VSC_STARTUP:
125                 argv[1] = "startup";
126                 break;
127         case VSC_SHUTDOWN:
128                 argv[1] = "shutdown";
129                 break;
130         default:
131                 return 0;
132         }
133
134         do_vshelper(vshelper_path, argv, envp, 1);
135         return 0;
136 }
137
138
139 /*
140  *      argv [0] = vshelper_path;
141  *      argv [1] = action: "netup", "netdown"
142  *      argv [2] = context identifier
143  *
144  *      envp [*] = type-specific parameters
145  */
146
147 long vs_net_change(struct nx_info *nxi, unsigned int cmd)
148 {
149         char id_buf[8], cmd_buf[16];
150         char *argv[] = {vshelper_path, NULL, id_buf, 0};
151         char *envp[] = {"HOME=/", "TERM=linux",
152                         "PATH=/sbin:/usr/sbin:/bin:/usr/bin", cmd_buf, 0};
153
154         if (!nx_info_flags(nxi, NXF_STATE_HELPER, 0))
155                 return 0;
156
157         snprintf(id_buf, sizeof(id_buf)-1, "%d", nxi->nx_id);
158         snprintf(cmd_buf, sizeof(cmd_buf)-1, "VS_CMD=%08x", cmd);
159
160         switch (cmd) {
161         case VSC_NETUP:
162                 argv[1] = "netup";
163                 break;
164         case VSC_NETDOWN:
165                 argv[1] = "netdown";
166                 break;
167         default:
168                 return 0;
169         }
170
171         do_vshelper(vshelper_path, argv, envp, 1);
172         return 0;
173 }
174