]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/commands.c
lxc-init: continue even if we fail to mount /dev/mqueue
[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:
9afe19d6 7 * Daniel Lezcano <daniel.lezcano at free.fr>
724e753c
MN
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 36#include <lxc/log.h>
ef6e34ee 37#include <lxc/lxc.h>
00b3c2e2
CLG
38#include <lxc/conf.h>
39#include <lxc/start.h> /* for struct lxc_handler */
2a59a681 40#include <lxc/utils.h>
724e753c
MN
41
42#include "commands.h"
ef6e34ee 43#include "confile.h"
724e753c
MN
44#include "mainloop.h"
45#include "af_unix.h"
adaeaa99 46#include "config.h"
724e753c 47
ded1d23f 48/*
ef6e34ee
DE
49 * This file provides the different functions for clients to
50 * query/command the server. The client is typically some lxc
51 * tool and the server is typically the container (ie. lxc-start).
ded1d23f 52 *
ef6e34ee
DE
53 * Each command is transactional, the clients send a request to
54 * the server and the server answers the request with a message
ded1d23f 55 * giving the request's status (zero or a negative errno value).
ef6e34ee 56 * Both the request and response may contain addtional data.
ded1d23f
DL
57 *
58 * Each command is wrapped in a ancillary message in order to pass
59 * a credential making possible to the server to check if the client
60 * is allowed to ask for this command or not.
ded1d23f
DL
61 */
62
724e753c
MN
63lxc_log_define(lxc_commands, lxc);
64
13f5be62
SH
65static int fill_sock_name(char *path, int len, const char *name,
66 const char *inpath)
67{
67e571de 68 const char *lxcpath = NULL;
2a59a681 69 int ret;
13f5be62
SH
70
71 if (!inpath) {
72 lxcpath = default_lxc_path();
73 if (!lxcpath) {
74 ERROR("Out of memory getting lxcpath");
75 return -1;
76 }
2a59a681 77 }
13f5be62 78 ret = snprintf(path, len, "%s/%s/command", lxcpath ? lxcpath : inpath, name);
13f5be62 79
2a59a681
SH
80 if (ret < 0 || ret >= len) {
81 ERROR("Name too long");
82 return -1;
83 }
84 return 0;
85}
ded1d23f 86
ef6e34ee 87static const char *lxc_cmd_str(lxc_cmd_t cmd)
724e753c 88{
ef6e34ee
DE
89 static const char *cmdname[LXC_CMD_MAX] = {
90 [LXC_CMD_CONSOLE] = "console",
91 [LXC_CMD_STOP] = "stop",
92 [LXC_CMD_GET_STATE] = "get_state",
93 [LXC_CMD_GET_INIT_PID] = "get_init_pid",
94 [LXC_CMD_GET_CLONE_FLAGS] = "get_clone_flags",
95 [LXC_CMD_GET_CGROUP] = "get_cgroup",
96 [LXC_CMD_GET_CONFIG_ITEM] = "get_config_item",
97 };
724e753c 98
ef6e34ee
DE
99 if (cmd < 0 || cmd >= LXC_CMD_MAX)
100 return "Unknown cmd";
101 return cmdname[cmd];
102}
103
104/*
105 * lxc_cmd_rsp_recv: Receive a response to a command
106 *
107 * @sock : the socket connected to the container
108 * @cmd : command to put response in
109 *
110 * Returns the size of the response message or < 0 on failure
111 *
112 * Note that if the command response datalen > 0, then data is
113 * a malloc()ed buffer and should be free()ed by the caller. If
114 * the response data is <= a void * worth of data, it will be
115 * stored directly in data and datalen will be 0.
116 *
117 * As a special case, the response for LXC_CMD_CONSOLE is created
0115f8fd
DE
118 * here as it contains an fd for the master pty passed through the
119 * unix socket.
ef6e34ee
DE
120 */
121static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
122{
123 int ret,rspfd;
124 struct lxc_cmd_rsp *rsp = &cmd->rsp;
125
126 ret = lxc_af_unix_recv_fd(sock, &rspfd, rsp, sizeof(*rsp));
127 if (ret < 0) {
128 ERROR("command %s failed to receive response",
129 lxc_cmd_str(cmd->req.cmd));
130 return -1;
131 }
132
133 if (cmd->req.cmd == LXC_CMD_CONSOLE) {
134 struct lxc_cmd_console_rsp_data *rspdata;
135
0115f8fd
DE
136 /* recv() returns 0 bytes when a tty cannot be allocated,
137 * rsp->ret is < 0 when the peer permission check failed
138 */
139 if (ret == 0 || rsp->ret < 0)
140 return 0;
141
ef6e34ee
DE
142 rspdata = malloc(sizeof(*rspdata));
143 if (!rspdata) {
144 ERROR("command %s couldn't allocate response buffer",
145 lxc_cmd_str(cmd->req.cmd));
146 return -1;
147 }
0115f8fd 148 rspdata->masterfd = rspfd;
ef6e34ee
DE
149 rspdata->ttynum = PTR_TO_INT(rsp->data);
150 rsp->data = rspdata;
151 }
152
153 if (rsp->datalen == 0)
ae5c8b8e 154 return ret;
ef6e34ee
DE
155 if (rsp->datalen > LXC_CMD_DATA_MAX) {
156 ERROR("command %s response data %d too long",
157 lxc_cmd_str(cmd->req.cmd), rsp->datalen);
158 errno = EFBIG;
2ac9aafc
SH
159 return -1;
160 }
ef6e34ee
DE
161
162 rsp->data = malloc(rsp->datalen);
163 if (!rsp->data) {
164 ERROR("command %s unable to allocate response buffer",
165 lxc_cmd_str(cmd->req.cmd));
166 return -1;
167 }
168 ret = recv(sock, rsp->data, rsp->datalen, 0);
169 if (ret != rsp->datalen) {
170 ERROR("command %s failed to receive response data",
171 lxc_cmd_str(cmd->req.cmd));
172 if (ret >= 0)
173 ret = -1;
174 }
724e753c
MN
175
176 return ret;
177}
178
ef6e34ee
DE
179/*
180 * lxc_cmd_rsp_send: Send a command response
181 *
182 * @fd : file descriptor of socket to send response on
183 * @rsp : response to send
184 *
185 * Returns 0 on success, < 0 on failure
186 */
187static int lxc_cmd_rsp_send(int fd, struct lxc_cmd_rsp *rsp)
188{
189 int ret;
190
191 ret = send(fd, rsp, sizeof(*rsp), 0);
192 if (ret != sizeof(*rsp)) {
193 ERROR("failed to send command response %d %s", ret,
194 strerror(errno));
195 return -1;
196 }
197
198 if (rsp->datalen > 0) {
199 ret = send(fd, rsp->data, rsp->datalen, 0);
200 if (ret != rsp->datalen) {
201 WARN("failed to send command response data %d %s", ret,
202 strerror(errno));
203 return -1;
204 }
205 }
206 return 0;
207}
208
209/*
210 * lxc_cmd: Connect to the specified running container, send it a command
211 * request and collect the response
212 *
213 * @name : name of container to connect to
214 * @cmd : command with initialized reqest to send
215 * @stopped : output indicator if the container was not running
216 * @lxcpath : the lxcpath in which the container is running
217 *
218 * Returns the size of the response message on success, < 0 on failure
219 *
220 * Note that there is a special case for LXC_CMD_CONSOLE. For this command
221 * the fd cannot be closed because it is used as a placeholder to indicate
222 * that a particular tty slot is in use. The fd is also used as a signal to
223 * the container that when the caller dies or closes the fd, the container
0115f8fd
DE
224 * will notice the fd on its side of the socket in its mainloop select and
225 * then free the slot with lxc_cmd_fd_cleanup(). The socket fd will be
226 * returned in the cmd response structure.
ef6e34ee
DE
227 */
228static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
229 const char *lxcpath)
724e753c 230{
724e753c 231 int sock, ret = -1;
46968ea3
DL
232 char path[sizeof(((struct sockaddr_un *)0)->sun_path)] = { 0 };
233 char *offset = &path[1];
2a59a681 234 int len;
ef6e34ee 235 int stay_connected = cmd->req.cmd == LXC_CMD_CONSOLE;
724e753c 236
9ba8130c 237 len = sizeof(path)-1;
13f5be62 238 if (fill_sock_name(offset, len, name, lxcpath))
9ba8130c 239 return -1;
724e753c 240
46968ea3 241 sock = lxc_af_unix_connect(path);
724e753c 242 if (sock < 0) {
ef6e34ee
DE
243 if (errno == ECONNREFUSED)
244 *stopped = 1;
245 else
246 SYSERROR("command %s failed to connect to '@%s'",
247 lxc_cmd_str(cmd->req.cmd), offset);
724e753c
MN
248 return -1;
249 }
250
ef6e34ee
DE
251 ret = lxc_af_unix_send_credential(sock, &cmd->req, sizeof(cmd->req));
252 if (ret != sizeof(cmd->req)) {
253 SYSERROR("command %s failed to send req to '@%s' %d",
254 lxc_cmd_str(cmd->req.cmd), offset, ret);
255 if (ret >=0)
256 ret = -1;
1362f2eb 257 goto out;
724e753c
MN
258 }
259
ef6e34ee
DE
260 if (cmd->req.datalen > 0) {
261 ret = send(sock, cmd->req.data, cmd->req.datalen, 0);
262 if (ret != cmd->req.datalen) {
263 SYSERROR("command %s failed to send request data to '@%s' %d",
264 lxc_cmd_str(cmd->req.cmd), offset, ret);
265 if (ret >=0)
266 ret = -1;
267 goto out;
268 }
724e753c
MN
269 }
270
ef6e34ee 271 ret = lxc_cmd_rsp_recv(sock, cmd);
724e753c 272out:
0115f8fd 273 if (!stay_connected || ret <= 0)
43eb6f29 274 close(sock);
0115f8fd
DE
275 if (stay_connected && ret > 0)
276 cmd->rsp.ret = sock;
43eb6f29 277
1362f2eb 278 return ret;
724e753c
MN
279}
280
ef6e34ee
DE
281/* Implentations of the commands and their callbacks */
282
283/*
284 * lxc_cmd_get_init_pid: Get pid of the container's init process
285 *
286 * @name : name of container to connect to
287 * @lxcpath : the lxcpath in which the container is running
288 *
289 * Returns the pid on success, < 0 on failure
290 */
291pid_t lxc_cmd_get_init_pid(const char *name, const char *lxcpath)
43eb6f29 292{
ef6e34ee
DE
293 int ret, stopped = 0;
294 struct lxc_cmd_rr cmd = {
295 .req = { .cmd = LXC_CMD_GET_INIT_PID },
296 };
297
298 ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
299 if (ret < 0)
300 return ret;
301
302 return PTR_TO_INT(cmd.rsp.data);
43eb6f29
DL
303}
304
ef6e34ee
DE
305static int lxc_cmd_get_init_pid_callback(int fd, struct lxc_cmd_req *req,
306 struct lxc_handler *handler)
43eb6f29 307{
ef6e34ee
DE
308 struct lxc_cmd_rsp rsp = { .data = INT_TO_PTR(handler->pid) };
309
310 return lxc_cmd_rsp_send(fd, &rsp);
43eb6f29
DL
311}
312
ef6e34ee
DE
313/*
314 * lxc_cmd_get_clone_flags: Get clone flags container was spawned with
315 *
316 * @name : name of container to connect to
317 * @lxcpath : the lxcpath in which the container is running
318 *
319 * Returns the clone flags on success, < 0 on failure
320 */
321int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath)
322{
323 int ret, stopped = 0;
324 struct lxc_cmd_rr cmd = {
325 .req = { .cmd = LXC_CMD_GET_CLONE_FLAGS },
326 };
327
328 ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
329 if (ret < 0)
330 return ret;
43eb6f29 331
ef6e34ee
DE
332 return PTR_TO_INT(cmd.rsp.data);
333}
334
335static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req,
336 struct lxc_handler *handler)
26b2d152 337{
ef6e34ee
DE
338 struct lxc_cmd_rsp rsp = { .data = INT_TO_PTR(handler->clone_flags) };
339
340 return lxc_cmd_rsp_send(fd, &rsp);
341}
342
343/*
344 * lxc_cmd_get_cgroup_path: Calculate a container's cgroup path for a
345 * particular subsystem. This is the cgroup path relative to the root
346 * of the cgroup filesystem.
347 *
ef6e34ee
DE
348 * @name : name of container to connect to
349 * @lxcpath : the lxcpath in which the container is running
350 *
351 * Returns the path on success, NULL on failure. The caller must free() the
352 * returned path.
353 */
2acf7795 354char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath)
ef6e34ee
DE
355{
356 int ret, stopped = 0;
357 struct lxc_cmd_rr cmd = {
358 .req = { .cmd = LXC_CMD_GET_CGROUP },
26b2d152
MN
359 };
360
ef6e34ee
DE
361 ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
362 if (ret < 0)
363 return NULL;
364
365 if (!ret) {
366 WARN("'%s' has stopped before sending its state", name);
367 return NULL;
368 }
369
370 if (cmd.rsp.ret < 0 || cmd.rsp.datalen < 0) {
371 ERROR("command %s failed for '%s': %s",
372 lxc_cmd_str(cmd.req.cmd), name,
373 strerror(-cmd.rsp.ret));
374 return NULL;
375 }
376
377 return cmd.rsp.data;
378}
379
380static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
381 struct lxc_handler *handler)
382{
383 struct lxc_cmd_rsp rsp = {
384 .datalen = strlen(handler->cgroup) + 1,
385 .data = handler->cgroup,
386 };
387
388 return lxc_cmd_rsp_send(fd, &rsp);
389}
390
391/*
392 * lxc_cmd_get_config_item: Get config item the running container
393 *
394 * @name : name of container to connect to
395 * @item : the configuration item to retrieve (ex: lxc.network.0.veth.pair)
396 * @lxcpath : the lxcpath in which the container is running
397 *
398 * Returns the item on success, NULL on failure. The caller must free() the
399 * returned item.
400 */
401char *lxc_cmd_get_config_item(const char *name, const char *item,
402 const char *lxcpath)
403{
404 int ret, stopped = 0;
405 struct lxc_cmd_rr cmd = {
406 .req = { .cmd = LXC_CMD_GET_CONFIG_ITEM,
407 .data = item,
408 .datalen = strlen(item)+1,
409 },
410 };
411
412 ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
413 if (ret < 0)
414 return NULL;
415
416 if (cmd.rsp.ret == 0)
417 return cmd.rsp.data;
418 return NULL;
419}
420
421static int lxc_cmd_get_config_item_callback(int fd, struct lxc_cmd_req *req,
422 struct lxc_handler *handler)
423{
424 int cilen;
425 struct lxc_cmd_rsp rsp;
426 char *cidata;
427
428 memset(&rsp, 0, sizeof(rsp));
429 cilen = lxc_get_config_item(handler->conf, req->data, NULL, 0);
430 if (cilen <= 0)
431 goto err1;
432
433 cidata = alloca(cilen + 1);
434 if (lxc_get_config_item(handler->conf, req->data, cidata, cilen + 1) != cilen)
435 goto err1;
436 cidata[cilen] = '\0';
437 rsp.data = cidata;
438 rsp.datalen = cilen + 1;
439 rsp.ret = 0;
440 goto out;
441
442err1:
443 rsp.ret = -1;
444out:
445 return lxc_cmd_rsp_send(fd, &rsp);
446}
447
448/*
449 * lxc_cmd_get_state: Get current state of the container
450 *
451 * @name : name of container to connect to
452 * @lxcpath : the lxcpath in which the container is running
453 *
454 * Returns the state on success, < 0 on failure
455 */
456lxc_state_t lxc_cmd_get_state(const char *name, const char *lxcpath)
457{
26b2d152 458 int ret, stopped = 0;
ef6e34ee
DE
459 struct lxc_cmd_rr cmd = {
460 .req = { .cmd = LXC_CMD_GET_STATE }
461 };
26b2d152 462
ef6e34ee 463 ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
ebdd307d 464 if (ret < 0 && stopped)
ef6e34ee
DE
465 return STOPPED;
466
467 if (ret < 0)
26b2d152 468 return -1;
26b2d152 469
ef6e34ee
DE
470 if (!ret) {
471 WARN("'%s' has stopped before sending its state", name);
472 return -1;
473 }
474
475 DEBUG("'%s' is in '%s' state", name,
476 lxc_state2str(PTR_TO_INT(cmd.rsp.data)));
477 return PTR_TO_INT(cmd.rsp.data);
478}
479
480static int lxc_cmd_get_state_callback(int fd, struct lxc_cmd_req *req,
481 struct lxc_handler *handler)
482{
483 struct lxc_cmd_rsp rsp = { .data = INT_TO_PTR(handler->state) };
484
485 return lxc_cmd_rsp_send(fd, &rsp);
486}
487
488/*
489 * lxc_cmd_stop: Stop the container previously started with lxc_start. All
490 * the processes running inside this container will be killed.
491 *
492 * @name : name of container to connect to
493 * @lxcpath : the lxcpath in which the container is running
494 *
495 * Returns 0 on success, < 0 on failure
496 */
497int lxc_cmd_stop(const char *name, const char *lxcpath)
498{
499 int ret, stopped = 0;
500 struct lxc_cmd_rr cmd = {
501 .req = { .cmd = LXC_CMD_STOP },
502 };
503
504 ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
26b2d152 505 if (ret < 0) {
ef6e34ee
DE
506 if (stopped) {
507 INFO("'%s' is already stopped", name);
508 return 0;
509 }
26b2d152
MN
510 return -1;
511 }
512
ef6e34ee
DE
513 /* we do not expect any answer, because we wait for the connection to be
514 * closed
515 */
516 if (ret > 0) {
517 ERROR("failed to stop '%s': %s", name, strerror(-cmd.rsp.ret));
26b2d152
MN
518 return -1;
519 }
520
ef6e34ee
DE
521 INFO("'%s' has stopped", name);
522 return 0;
26b2d152
MN
523}
524
ef6e34ee
DE
525static int lxc_cmd_stop_callback(int fd, struct lxc_cmd_req *req,
526 struct lxc_handler *handler)
d5088cf2 527{
ef6e34ee
DE
528 struct lxc_cmd_rsp rsp;
529 int ret;
530 int stopsignal = SIGKILL;
531
532 if (handler->conf->stopsignal)
533 stopsignal = handler->conf->stopsignal;
534 memset(&rsp, 0, sizeof(rsp));
535 rsp.ret = kill(handler->pid, stopsignal);
536 if (!rsp.ret) {
537 ret = lxc_unfreeze_bypath(handler->cgroup);
538 if (!ret)
539 return 0;
540
541 ERROR("failed to unfreeze container");
542 rsp.ret = ret;
543 }
544
545 return lxc_cmd_rsp_send(fd, &rsp);
546}
d5088cf2 547
ef6e34ee
DE
548/*
549 * lxc_cmd_console: Open an fd to a tty in the container
550 *
551 * @name : name of container to connect to
552 * @ttynum : in: the tty to open or -1 for next available
553 * : out: the tty allocated
554 * @fd : out: file descriptor for master side of pty
555 * @lxcpath : the lxcpath in which the container is running
556 *
0115f8fd 557 * Returns fd holding tty allocated on success, < 0 on failure
ef6e34ee
DE
558 */
559int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
560{
d5088cf2 561 int ret, stopped = 0;
ef6e34ee
DE
562 struct lxc_cmd_console_rsp_data *rspdata;
563 struct lxc_cmd_rr cmd = {
564 .req = { .cmd = LXC_CMD_CONSOLE, .data = INT_TO_PTR(*ttynum) },
565 };
d5088cf2 566
ef6e34ee
DE
567 ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
568 if (ret < 0)
569 return ret;
0115f8fd
DE
570
571 if (cmd.rsp.ret < 0) {
572 ERROR("console access denied: %s", strerror(-cmd.rsp.ret));
ef6e34ee
DE
573 ret = -1;
574 goto out;
575 }
d5088cf2 576
0115f8fd
DE
577 if (ret == 0) {
578 ERROR("console %d invalid,busy or all consoles busy", *ttynum);
579 ret = -1;
ef6e34ee
DE
580 goto out;
581 }
ef6e34ee
DE
582
583 rspdata = cmd.rsp.data;
0115f8fd 584 if (rspdata->masterfd < 0) {
ef6e34ee
DE
585 ERROR("unable to allocate fd for tty %d", rspdata->ttynum);
586 goto out;
587 }
588
0115f8fd
DE
589 ret = cmd.rsp.ret; /* sock fd */
590 *fd = rspdata->masterfd;
ef6e34ee 591 *ttynum = rspdata->ttynum;
0115f8fd 592 INFO("tty %d allocated fd %d sock %d", rspdata->ttynum, *fd, ret);
ef6e34ee
DE
593out:
594 free(cmd.rsp.data);
595 return ret;
596}
597
598static int lxc_cmd_console_callback(int fd, struct lxc_cmd_req *req,
599 struct lxc_handler *handler)
600{
601 int ttynum = PTR_TO_INT(req->data);
602 struct lxc_tty_info *tty_info = &handler->conf->tty_info;
603 struct lxc_cmd_rsp rsp;
604
605 if (ttynum > 0) {
606 if (ttynum > tty_info->nbtty)
607 goto out_close;
608
609 if (tty_info->pty_info[ttynum - 1].busy)
610 goto out_close;
611
612 /* the requested tty is available */
613 goto out_send;
d5088cf2
CS
614 }
615
ef6e34ee
DE
616 /* search for next available tty, fixup index tty1 => [0] */
617 for (ttynum = 1;
618 ttynum <= tty_info->nbtty && tty_info->pty_info[ttynum - 1].busy;
619 ttynum++);
620
621 /* we didn't find any available slot for tty */
622 if (ttynum > tty_info->nbtty)
623 goto out_close;
624
625out_send:
626 memset(&rsp, 0, sizeof(rsp));
627 rsp.data = INT_TO_PTR(ttynum);
628 if (lxc_af_unix_send_fd(fd, tty_info->pty_info[ttynum - 1].master,
629 &rsp, sizeof(rsp)) < 0) {
630 ERROR("failed to send tty to client");
631 goto out_close;
632 }
633
634 tty_info->pty_info[ttynum - 1].busy = fd;
635 return 0;
636
637out_close:
638 /* special indicator to lxc_cmd_handler() to close the fd and do
639 * related cleanup
640 */
641 return 1;
d5088cf2
CS
642}
643
724e753c 644
ef6e34ee
DE
645
646static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
ded1d23f 647 struct lxc_handler *handler)
724e753c 648{
ef6e34ee
DE
649 typedef int (*callback)(int, struct lxc_cmd_req *, struct lxc_handler *);
650
651 callback cb[LXC_CMD_MAX] = {
652 [LXC_CMD_CONSOLE] = lxc_cmd_console_callback,
653 [LXC_CMD_STOP] = lxc_cmd_stop_callback,
654 [LXC_CMD_GET_STATE] = lxc_cmd_get_state_callback,
655 [LXC_CMD_GET_INIT_PID] = lxc_cmd_get_init_pid_callback,
656 [LXC_CMD_GET_CLONE_FLAGS] = lxc_cmd_get_clone_flags_callback,
657 [LXC_CMD_GET_CGROUP] = lxc_cmd_get_cgroup_callback,
658 [LXC_CMD_GET_CONFIG_ITEM] = lxc_cmd_get_config_item_callback,
724e753c
MN
659 };
660
ef6e34ee
DE
661 if (req->cmd < 0 || req->cmd >= LXC_CMD_MAX) {
662 ERROR("bad cmd %d recieved", req->cmd);
724e753c 663 return -1;
ef6e34ee
DE
664 }
665 return cb[req->cmd](fd, req, handler);
724e753c
MN
666}
667
ef6e34ee 668static void lxc_cmd_fd_cleanup(int fd, struct lxc_handler *handler,
ded1d23f 669 struct lxc_epoll_descr *descr)
724e753c 670{
ef6e34ee 671 extern void lxc_console_remove_fd(int, struct lxc_tty_info *);
fae349da 672 lxc_console_remove_fd(fd, &handler->conf->tty_info);
724e753c
MN
673 lxc_mainloop_del_handler(descr, fd);
674 close(fd);
675}
676
ef6e34ee 677static int lxc_cmd_handler(int fd, void *data, struct lxc_epoll_descr *descr)
724e753c
MN
678{
679 int ret;
ef6e34ee 680 struct lxc_cmd_req req;
724e753c
MN
681 struct lxc_handler *handler = data;
682
ef6e34ee 683 ret = lxc_af_unix_rcv_credential(fd, &req, sizeof(req));
0a3ec350 684 if (ret == -EACCES) {
3cc5de36 685 /* we don't care for the peer, just send and close */
ef6e34ee
DE
686 struct lxc_cmd_rsp rsp = { .ret = ret };
687
688 lxc_cmd_rsp_send(fd, &rsp);
3cc5de36 689 goto out_close;
ded1d23f
DL
690 }
691
692 if (ret < 0) {
724e753c
MN
693 SYSERROR("failed to receive data on command socket");
694 goto out_close;
695 }
696
697 if (!ret) {
698 DEBUG("peer has disconnected");
699 goto out_close;
700 }
701
ef6e34ee 702 if (ret != sizeof(req)) {
724e753c 703 WARN("partial request, ignored");
ef6e34ee
DE
704 ret = -1;
705 goto out_close;
706 }
707
708 if (req.datalen > LXC_CMD_DATA_MAX) {
709 ERROR("cmd data length %d too large", req.datalen);
710 ret = -1;
724e753c
MN
711 goto out_close;
712 }
713
ef6e34ee
DE
714 if (req.datalen > 0) {
715 void *reqdata;
716
717 reqdata = alloca(req.datalen);
718 ret = recv(fd, reqdata, req.datalen, 0);
719 if (ret != req.datalen) {
720 WARN("partial request, ignored");
721 ret = -1;
722 goto out_close;
723 }
724 req.data = reqdata;
725 }
726
727 ret = lxc_cmd_process(fd, &req, handler);
724e753c
MN
728 if (ret) {
729 /* this is not an error, but only a request to close fd */
730 ret = 0;
731 goto out_close;
732 }
733
734out:
735 return ret;
736out_close:
ef6e34ee 737 lxc_cmd_fd_cleanup(fd, handler, descr);
724e753c
MN
738 goto out;
739}
740
ef6e34ee 741static int lxc_cmd_accept(int fd, void *data, struct lxc_epoll_descr *descr)
724e753c 742{
ded1d23f 743 int opt = 1, ret = -1, connection;
724e753c
MN
744
745 connection = accept(fd, NULL, 0);
746 if (connection < 0) {
747 SYSERROR("failed to accept connection");
748 return -1;
749 }
750
9ccb2dbc
DL
751 if (fcntl(connection, F_SETFD, FD_CLOEXEC)) {
752 SYSERROR("failed to set close-on-exec on incoming connection");
753 goto out_close;
754 }
755
0a3ec350
DL
756 if (setsockopt(connection, SOL_SOCKET,
757 SO_PASSCRED, &opt, sizeof(opt))) {
724e753c
MN
758 SYSERROR("failed to enable credential on socket");
759 goto out_close;
760 }
761
ef6e34ee 762 ret = lxc_mainloop_add_handler(descr, connection, lxc_cmd_handler, data);
724e753c
MN
763 if (ret) {
764 ERROR("failed to add handler");
765 goto out_close;
766 }
767
768out:
769 return ret;
770
771out_close:
772 close(connection);
773 goto out;
774}
775
ef6e34ee
DE
776int lxc_cmd_init(const char *name, struct lxc_handler *handler,
777 const char *lxcpath)
724e753c 778{
d2e30e99 779 int fd;
46968ea3
DL
780 char path[sizeof(((struct sockaddr_un *)0)->sun_path)] = { 0 };
781 char *offset = &path[1];
2a59a681 782 int len;
724e753c 783
9ba8130c 784 len = sizeof(path)-1;
13f5be62 785 if (fill_sock_name(offset, len, name, lxcpath))
9ba8130c 786 return -1;
724e753c 787
46968ea3 788 fd = lxc_af_unix_open(path, SOCK_STREAM, 0);
724e753c 789 if (fd < 0) {
97d3756c
SH
790 ERROR("failed (%d) to create the command service point %s", errno, offset);
791 if (errno == EADDRINUSE) {
792 ERROR("##");
793 ERROR("# The container appears to be already running!");
794 ERROR("##");
795 }
724e753c
MN
796 return -1;
797 }
798
91480a0f
DL
799 if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
800 SYSERROR("failed to set sigfd to close-on-exec");
801 close(fd);
802 return -1;
803 }
804
d2e30e99
DE
805 handler->conf->maincmd_fd = fd;
806 return 0;
807}
808
ef6e34ee
DE
809int lxc_cmd_mainloop_add(const char *name,
810 struct lxc_epoll_descr *descr,
811 struct lxc_handler *handler)
d2e30e99
DE
812{
813 int ret, fd = handler->conf->maincmd_fd;
814
ef6e34ee 815 ret = lxc_mainloop_add_handler(descr, fd, lxc_cmd_accept, handler);
724e753c
MN
816 if (ret) {
817 ERROR("failed to add handler for command socket");
818 close(fd);
819 }
820
821 return ret;
822}