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