]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/commands.c
pass lxcpath to lxc_command
[mirror_lxc.git] / src / lxc / commands.c
CommitLineData
724e753c
MN
1/*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2009
5 *
6 * Authors:
7 * Daniel Lezcano <dlezcano at fr.ibm.com>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include <stdio.h>
25#include <errno.h>
26#include <unistd.h>
27#include <signal.h>
91480a0f 28#include <fcntl.h>
724e753c
MN
29#include <sys/socket.h>
30#include <sys/un.h>
31#include <sys/poll.h>
32#include <sys/param.h>
2a59a681
SH
33#include <malloc.h>
34#include <stdlib.h>
724e753c 35
00b3c2e2
CLG
36#include <lxc/log.h>
37#include <lxc/conf.h>
38#include <lxc/start.h> /* for struct lxc_handler */
2a59a681 39#include <lxc/utils.h>
724e753c
MN
40
41#include "commands.h"
42#include "mainloop.h"
43#include "af_unix.h"
adaeaa99 44#include "config.h"
724e753c 45
ded1d23f
DL
46/*
47 * This file provides the different functions to have the client
48 * and the server to communicate
49 *
50 * Each command is transactional, the client send a request to
51 * the server and the server answer the request with a message
52 * giving the request's status (zero or a negative errno value).
53 *
54 * Each command is wrapped in a ancillary message in order to pass
55 * a credential making possible to the server to check if the client
56 * is allowed to ask for this command or not.
57 *
58 */
59
724e753c
MN
60lxc_log_define(lxc_commands, lxc);
61
13f5be62
SH
62static int fill_sock_name(char *path, int len, const char *name,
63 const char *inpath)
64{
65 char *lxcpath = NULL;
2a59a681 66 int ret;
13f5be62
SH
67
68 if (!inpath) {
69 lxcpath = default_lxc_path();
70 if (!lxcpath) {
71 ERROR("Out of memory getting lxcpath");
72 return -1;
73 }
2a59a681 74 }
13f5be62
SH
75 ret = snprintf(path, len, "%s/%s/command", lxcpath ? lxcpath : inpath, name);
76 if (lxcpath)
77 free(lxcpath);
78
2a59a681
SH
79 if (ret < 0 || ret >= len) {
80 ERROR("Name too long");
81 return -1;
82 }
83 return 0;
84}
ded1d23f 85
724e753c
MN
86static int receive_answer(int sock, struct lxc_answer *answer)
87{
88 int ret;
89
90 ret = lxc_af_unix_recv_fd(sock, &answer->fd, answer, sizeof(*answer));
91 if (ret < 0)
92 ERROR("failed to receive answer for the command");
93
94 return ret;
95}
96
43eb6f29 97static int __lxc_command(const char *name, struct lxc_command *command,
13f5be62 98 int *stopped, int stay_connected, const char *lxcpath)
724e753c 99{
724e753c 100 int sock, ret = -1;
46968ea3
DL
101 char path[sizeof(((struct sockaddr_un *)0)->sun_path)] = { 0 };
102 char *offset = &path[1];
2a59a681 103 int len;
724e753c 104
9ba8130c 105 len = sizeof(path)-1;
13f5be62 106 if (fill_sock_name(offset, len, name, lxcpath))
9ba8130c 107 return -1;
724e753c 108
46968ea3 109 sock = lxc_af_unix_connect(path);
d97b36f8
DL
110 if (sock < 0 && errno == ECONNREFUSED) {
111 *stopped = 1;
112 return -1;
113 }
114
724e753c 115 if (sock < 0) {
d97b36f8 116 SYSERROR("failed to connect to '@%s'", offset);
724e753c
MN
117 return -1;
118 }
119
120 ret = lxc_af_unix_send_credential(sock, &command->request,
121 sizeof(command->request));
122 if (ret < 0) {
d97b36f8 123 SYSERROR("failed to send request to '@%s'", offset);
1362f2eb 124 goto out;
724e753c
MN
125 }
126
127 if (ret != sizeof(command->request)) {
d97b36f8 128 SYSERROR("message partially sent to '@%s'", offset);
1362f2eb 129 goto out;
724e753c
MN
130 }
131
132 ret = receive_answer(sock, &command->answer);
724e753c 133out:
43eb6f29
DL
134 if (!stay_connected || ret < 0)
135 close(sock);
136
1362f2eb 137 return ret;
724e753c
MN
138}
139
43eb6f29 140extern int lxc_command(const char *name,
13f5be62
SH
141 struct lxc_command *command, int *stopped,
142 const char *lxcpath)
43eb6f29 143{
13f5be62 144 return __lxc_command(name, command, stopped, 0, lxcpath);
43eb6f29
DL
145}
146
147extern int lxc_command_connected(const char *name,
13f5be62
SH
148 struct lxc_command *command, int *stopped,
149 const char *lxcpath)
43eb6f29 150{
13f5be62 151 return __lxc_command(name, command, stopped, 1, lxcpath);
43eb6f29
DL
152}
153
154
13f5be62 155pid_t get_init_pid(const char *name, const char *lxcpath)
26b2d152
MN
156{
157 struct lxc_command command = {
158 .request = { .type = LXC_COMMAND_PID },
159 };
160
161 int ret, stopped = 0;
162
13f5be62 163 ret = lxc_command(name, &command, &stopped, lxcpath);
ebdd307d 164 if (ret < 0 && stopped)
26b2d152 165 return -1;
26b2d152
MN
166
167 if (ret < 0) {
168 ERROR("failed to send command");
169 return -1;
170 }
171
172 if (command.answer.ret) {
173 ERROR("failed to retrieve the init pid: %s",
174 strerror(-command.answer.ret));
175 return -1;
176 }
177
178 return command.answer.pid;
179}
180
13f5be62 181int lxc_get_clone_flags(const char *name, const char *lxcpath)
d5088cf2
CS
182{
183 struct lxc_command command = {
184 .request = { .type = LXC_COMMAND_CLONE_FLAGS },
185 };
186
187 int ret, stopped = 0;
188
13f5be62 189 ret = lxc_command(name, &command, &stopped, lxcpath);
d5088cf2
CS
190 if (ret < 0 && stopped)
191 return -1;
192
193 if (ret < 0) {
194 ERROR("failed to send command");
195 return -1;
196 }
197
198 return command.answer.ret;
199}
200
ded1d23f
DL
201extern void lxc_console_remove_fd(int, struct lxc_tty_info *);
202extern int lxc_console_callback(int, struct lxc_request *, struct lxc_handler *);
203extern int lxc_stop_callback(int, struct lxc_request *, struct lxc_handler *);
204extern int lxc_state_callback(int, struct lxc_request *, struct lxc_handler *);
81c75799 205extern int lxc_pid_callback(int, struct lxc_request *, struct lxc_handler *);
d5088cf2 206extern int lxc_clone_flags_callback(int, struct lxc_request *, struct lxc_handler *);
724e753c
MN
207
208static int trigger_command(int fd, struct lxc_request *request,
ded1d23f 209 struct lxc_handler *handler)
724e753c 210{
ded1d23f 211 typedef int (*callback)(int, struct lxc_request *, struct lxc_handler *);
724e753c
MN
212
213 callback cb[LXC_COMMAND_MAX] = {
d5088cf2
CS
214 [LXC_COMMAND_TTY] = lxc_console_callback,
215 [LXC_COMMAND_STOP] = lxc_stop_callback,
216 [LXC_COMMAND_STATE] = lxc_state_callback,
217 [LXC_COMMAND_PID] = lxc_pid_callback,
218 [LXC_COMMAND_CLONE_FLAGS] = lxc_clone_flags_callback,
724e753c
MN
219 };
220
221 if (request->type < 0 || request->type >= LXC_COMMAND_MAX)
222 return -1;
223
224 return cb[request->type](fd, request, handler);
225}
226
227static void command_fd_cleanup(int fd, struct lxc_handler *handler,
ded1d23f 228 struct lxc_epoll_descr *descr)
724e753c 229{
fae349da 230 lxc_console_remove_fd(fd, &handler->conf->tty_info);
724e753c
MN
231 lxc_mainloop_del_handler(descr, fd);
232 close(fd);
233}
234
ded1d23f 235static int command_handler(int fd, void *data, struct lxc_epoll_descr *descr)
724e753c
MN
236{
237 int ret;
238 struct lxc_request request;
239 struct lxc_handler *handler = data;
240
241 ret = lxc_af_unix_rcv_credential(fd, &request, sizeof(request));
0a3ec350 242 if (ret == -EACCES) {
3cc5de36
MN
243 /* we don't care for the peer, just send and close */
244 struct lxc_answer answer = { .ret = ret };
245 send(fd, &answer, sizeof(answer), 0);
246 goto out_close;
ded1d23f
DL
247 }
248
249 if (ret < 0) {
724e753c
MN
250 SYSERROR("failed to receive data on command socket");
251 goto out_close;
252 }
253
254 if (!ret) {
255 DEBUG("peer has disconnected");
256 goto out_close;
257 }
258
259 if (ret != sizeof(request)) {
260 WARN("partial request, ignored");
261 goto out_close;
262 }
263
264 ret = trigger_command(fd, &request, handler);
265 if (ret) {
266 /* this is not an error, but only a request to close fd */
267 ret = 0;
268 goto out_close;
269 }
270
271out:
272 return ret;
273out_close:
274 command_fd_cleanup(fd, handler, descr);
275 goto out;
276}
277
278static int incoming_command_handler(int fd, void *data,
279 struct lxc_epoll_descr *descr)
280{
ded1d23f 281 int opt = 1, ret = -1, connection;
724e753c
MN
282
283 connection = accept(fd, NULL, 0);
284 if (connection < 0) {
285 SYSERROR("failed to accept connection");
286 return -1;
287 }
288
9ccb2dbc
DL
289 if (fcntl(connection, F_SETFD, FD_CLOEXEC)) {
290 SYSERROR("failed to set close-on-exec on incoming connection");
291 goto out_close;
292 }
293
0a3ec350
DL
294 if (setsockopt(connection, SOL_SOCKET,
295 SO_PASSCRED, &opt, sizeof(opt))) {
724e753c
MN
296 SYSERROR("failed to enable credential on socket");
297 goto out_close;
298 }
299
300 ret = lxc_mainloop_add_handler(descr, connection, command_handler, data);
301 if (ret) {
302 ERROR("failed to add handler");
303 goto out_close;
304 }
305
306out:
307 return ret;
308
309out_close:
310 close(connection);
311 goto out;
312}
313
13f5be62
SH
314extern int lxc_command_init(const char *name, struct lxc_handler *handler,
315 const char *lxcpath)
724e753c 316{
d2e30e99 317 int fd;
46968ea3
DL
318 char path[sizeof(((struct sockaddr_un *)0)->sun_path)] = { 0 };
319 char *offset = &path[1];
2a59a681 320 int len;
724e753c 321
9ba8130c 322 len = sizeof(path)-1;
13f5be62 323 if (fill_sock_name(offset, len, name, lxcpath))
9ba8130c 324 return -1;
724e753c 325
46968ea3 326 fd = lxc_af_unix_open(path, SOCK_STREAM, 0);
724e753c 327 if (fd < 0) {
97d3756c
SH
328 ERROR("failed (%d) to create the command service point %s", errno, offset);
329 if (errno == EADDRINUSE) {
330 ERROR("##");
331 ERROR("# The container appears to be already running!");
332 ERROR("##");
333 }
724e753c
MN
334 return -1;
335 }
336
91480a0f
DL
337 if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
338 SYSERROR("failed to set sigfd to close-on-exec");
339 close(fd);
340 return -1;
341 }
342
d2e30e99
DE
343 handler->conf->maincmd_fd = fd;
344 return 0;
345}
346
347extern int lxc_command_mainloop_add(const char *name,
348 struct lxc_epoll_descr *descr,
349 struct lxc_handler *handler)
350{
351 int ret, fd = handler->conf->maincmd_fd;
352
0a3ec350
DL
353 ret = lxc_mainloop_add_handler(descr, fd, incoming_command_handler,
354 handler);
724e753c
MN
355 if (ret) {
356 ERROR("failed to add handler for command socket");
357 close(fd);
358 }
359
360 return ret;
361}