2 * lxc: linux Container library
4 * (C) Copyright IBM Corp. 2007, 2009
7 * Daniel Lezcano <daniel.lezcano at free.fr>
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30 #include <sys/socket.h>
33 #include <sys/param.h>
40 #include "start.h" /* for struct lxc_handler */
53 * This file provides the different functions for clients to
54 * query/command the server. The client is typically some lxc
55 * tool and the server is typically the container (ie. lxc-start).
57 * Each command is transactional, the clients send a request to
58 * the server and the server answers the request with a message
59 * giving the request's status (zero or a negative errno value).
60 * Both the request and response may contain additional data.
62 * Each command is wrapped in a ancillary message in order to pass
63 * a credential making possible to the server to check if the client
64 * is allowed to ask for this command or not.
66 * IMPORTANTLY: Note that semantics for current commands are fixed. If you
67 * wish to make any changes to how, say, LXC_CMD_GET_CONFIG_ITEM works by
68 * adding information to the end of cmd.data, then you must introduce a new
69 * LXC_CMD_GET_CONFIG_ITEM_V2 define with a new number. You may wish to
70 * also mark LXC_CMD_GET_CONFIG_ITEM deprecated in commands.h.
72 * This is necessary in order to avoid having a newly compiled lxc command
73 * communicating with a running (old) monitor from crashing the running
77 lxc_log_define(lxc_commands
, lxc
);
79 static int fill_sock_name(char *path
, int len
, const char *lxcname
,
80 const char *lxcpath
, const char *hashed_sock_name
)
92 if (hashed_sock_name
!= NULL
) {
93 ret
= snprintf(path
, len
, "lxc/%s/command", hashed_sock_name
);
94 if (ret
< 0 || ret
>= len
) {
95 ERROR("Error writing to command sock path");
102 lxcpath
= lxc_global_config_value("lxc.lxcpath");
104 ERROR("Out of memory getting lxcpath");
109 ret
= snprintf(path
, len
, "%s/%s/command", lxcpath
, name
);
111 ERROR("Error writing to command sock path");
117 /* ret >= len; lxcpath or name is too long. hash both */
118 tmplen
= strlen(name
) + strlen(lxcpath
) + 2;
119 tmppath
= alloca(tmplen
);
120 ret
= snprintf(tmppath
, tmplen
, "%s/%s", lxcpath
, name
);
121 if (ret
< 0 || ret
>= tmplen
) {
122 ERROR("memory error");
125 hash
= fnv_64a_buf(tmppath
, ret
, FNV1A_64_INIT
);
126 ret
= snprintf(path
, len
, "lxc/%016" PRIx64
"/command", hash
);
127 if (ret
< 0 || ret
>= len
) {
128 ERROR("Command socket name too long");
135 static const char *lxc_cmd_str(lxc_cmd_t cmd
)
137 static const char * const cmdname
[LXC_CMD_MAX
] = {
138 [LXC_CMD_CONSOLE
] = "console",
139 [LXC_CMD_STOP
] = "stop",
140 [LXC_CMD_GET_STATE
] = "get_state",
141 [LXC_CMD_GET_INIT_PID
] = "get_init_pid",
142 [LXC_CMD_GET_CLONE_FLAGS
] = "get_clone_flags",
143 [LXC_CMD_GET_CGROUP
] = "get_cgroup",
144 [LXC_CMD_GET_CONFIG_ITEM
] = "get_config_item",
145 [LXC_CMD_GET_NAME
] = "get_name",
146 [LXC_CMD_GET_LXCPATH
] = "get_lxcpath",
147 [LXC_CMD_STATE_SERVER
] = "state_server",
150 if (cmd
>= LXC_CMD_MAX
)
151 return "Unknown cmd";
156 * lxc_cmd_rsp_recv: Receive a response to a command
158 * @sock : the socket connected to the container
159 * @cmd : command to put response in
161 * Returns the size of the response message or < 0 on failure
163 * Note that if the command response datalen > 0, then data is
164 * a malloc()ed buffer and should be free()ed by the caller. If
165 * the response data is <= a void * worth of data, it will be
166 * stored directly in data and datalen will be 0.
168 * As a special case, the response for LXC_CMD_CONSOLE is created
169 * here as it contains an fd for the master pty passed through the
172 static int lxc_cmd_rsp_recv(int sock
, struct lxc_cmd_rr
*cmd
)
175 struct lxc_cmd_rsp
*rsp
= &cmd
->rsp
;
177 ret
= lxc_abstract_unix_recv_fds(sock
, &rspfd
, 1, rsp
, sizeof(*rsp
));
179 WARN("Command %s failed to receive response: %s.",
180 lxc_cmd_str(cmd
->req
.cmd
), strerror(errno
));
184 if (cmd
->req
.cmd
== LXC_CMD_CONSOLE
) {
185 struct lxc_cmd_console_rsp_data
*rspdata
;
187 /* recv() returns 0 bytes when a tty cannot be allocated,
188 * rsp->ret is < 0 when the peer permission check failed
190 if (ret
== 0 || rsp
->ret
< 0)
193 rspdata
= malloc(sizeof(*rspdata
));
195 ERROR("Command %s couldn't allocate response buffer.",
196 lxc_cmd_str(cmd
->req
.cmd
));
199 rspdata
->masterfd
= rspfd
;
200 rspdata
->ttynum
= PTR_TO_INT(rsp
->data
);
204 if (rsp
->datalen
== 0) {
205 DEBUG("command %s response data length is 0",
206 lxc_cmd_str(cmd
->req
.cmd
));
209 if (rsp
->datalen
> LXC_CMD_DATA_MAX
) {
210 ERROR("Command %s response data %d too long.",
211 lxc_cmd_str(cmd
->req
.cmd
), rsp
->datalen
);
216 rsp
->data
= malloc(rsp
->datalen
);
218 ERROR("Command %s was unable to allocate response buffer.",
219 lxc_cmd_str(cmd
->req
.cmd
));
222 ret
= recv(sock
, rsp
->data
, rsp
->datalen
, 0);
223 if (ret
!= rsp
->datalen
) {
224 ERROR("Command %s failed to receive response data: %s.",
225 lxc_cmd_str(cmd
->req
.cmd
), strerror(errno
));
234 * lxc_cmd_rsp_send: Send a command response
236 * @fd : file descriptor of socket to send response on
237 * @rsp : response to send
239 * Returns 0 on success, < 0 on failure
241 static int lxc_cmd_rsp_send(int fd
, struct lxc_cmd_rsp
*rsp
)
245 ret
= send(fd
, rsp
, sizeof(*rsp
), 0);
246 if (ret
!= sizeof(*rsp
)) {
247 ERROR("Failed to send command response %d: %s.", ret
,
252 if (rsp
->datalen
> 0) {
253 ret
= send(fd
, rsp
->data
, rsp
->datalen
, 0);
254 if (ret
!= rsp
->datalen
) {
255 WARN("Failed to send command response data %d: %s.",
256 ret
, strerror(errno
));
264 * lxc_cmd: Connect to the specified running container, send it a command
265 * request and collect the response
267 * @name : name of container to connect to
268 * @cmd : command with initialized reqest to send
269 * @stopped : output indicator if the container was not running
270 * @lxcpath : the lxcpath in which the container is running
272 * Returns the size of the response message on success, < 0 on failure
274 * Note that there is a special case for LXC_CMD_CONSOLE. For this command
275 * the fd cannot be closed because it is used as a placeholder to indicate
276 * that a particular tty slot is in use. The fd is also used as a signal to
277 * the container that when the caller dies or closes the fd, the container
278 * will notice the fd on its side of the socket in its mainloop select and
279 * then free the slot with lxc_cmd_fd_cleanup(). The socket fd will be
280 * returned in the cmd response structure.
282 static int lxc_cmd(const char *name
, struct lxc_cmd_rr
*cmd
, int *stopped
,
283 const char *lxcpath
, const char *hashed_sock_name
)
286 char path
[sizeof(((struct sockaddr_un
*)0)->sun_path
)] = { 0 };
287 char *offset
= &path
[1];
289 bool stay_connected
= false;
291 if (cmd
->req
.cmd
== LXC_CMD_CONSOLE
||
292 cmd
->req
.cmd
== LXC_CMD_STATE_SERVER
)
293 stay_connected
= true;
297 /* -2 here because this is an abstract unix socket so it needs a
298 * leading \0, and we null terminate, so it needs a trailing \0.
299 * Although null termination isn't required by the API, we do it anyway
300 * because we print the sockname out sometimes.
302 len
= sizeof(path
)-2;
303 if (fill_sock_name(offset
, len
, name
, lxcpath
, hashed_sock_name
))
306 sock
= lxc_abstract_unix_connect(path
);
307 TRACE("command %s tries to connect to \"@%s\"",
308 lxc_cmd_str(cmd
->req
.cmd
), offset
);
310 if (errno
== ECONNREFUSED
) {
311 TRACE("command %s failed to connect to \"@%s\": %s",
312 lxc_cmd_str(cmd
->req
.cmd
), offset
,
316 SYSERROR("command %s failed to connect to \"@%s\": %s",
317 lxc_cmd_str(cmd
->req
.cmd
), offset
,
324 ret
= lxc_abstract_unix_send_credential(sock
, &cmd
->req
, sizeof(cmd
->req
));
325 if (ret
!= sizeof(cmd
->req
)) {
328 SYSERROR("Command %s failed to send req to \"@%s\" %d.",
329 lxc_cmd_str(cmd
->req
.cmd
), offset
, ret
);
335 if (cmd
->req
.datalen
> 0) {
336 ret
= send(sock
, cmd
->req
.data
, cmd
->req
.datalen
, MSG_NOSIGNAL
);
337 if (ret
!= cmd
->req
.datalen
) {
340 SYSERROR("Command %s failed to send request data to \"@%s\" %d.",
341 lxc_cmd_str(cmd
->req
.cmd
), offset
, ret
);
348 ret
= lxc_cmd_rsp_recv(sock
, cmd
);
350 if (!stay_connected
|| ret
<= 0)
352 if (stay_connected
&& ret
> 0)
363 int lxc_try_cmd(const char *name
, const char *lxcpath
)
366 struct lxc_cmd_rr cmd
= {
367 .req
= { .cmd
= LXC_CMD_GET_INIT_PID
},
370 ret
= lxc_cmd(name
, &cmd
, &stopped
, lxcpath
, NULL
);
374 if (ret
> 0 && cmd
.rsp
.ret
< 0) {
382 * At this point we weren't denied access, and the
383 * container *was* started. There was some inexplicable
384 * error in the protocol.
385 * I'm not clear on whether we should return -1 here, but
386 * we didn't receive a -EACCES, so technically it's not that
387 * we're not allowed to control the container - it's just not
393 /* Implentations of the commands and their callbacks */
396 * lxc_cmd_get_init_pid: Get pid of the container's init process
398 * @name : name of container to connect to
399 * @lxcpath : the lxcpath in which the container is running
401 * Returns the pid on success, < 0 on failure
403 pid_t
lxc_cmd_get_init_pid(const char *name
, const char *lxcpath
)
406 struct lxc_cmd_rr cmd
= {
407 .req
= { .cmd
= LXC_CMD_GET_INIT_PID
},
410 ret
= lxc_cmd(name
, &cmd
, &stopped
, lxcpath
, NULL
);
414 return PTR_TO_INT(cmd
.rsp
.data
);
417 static int lxc_cmd_get_init_pid_callback(int fd
, struct lxc_cmd_req
*req
,
418 struct lxc_handler
*handler
)
420 struct lxc_cmd_rsp rsp
= { .data
= INT_TO_PTR(handler
->pid
) };
422 return lxc_cmd_rsp_send(fd
, &rsp
);
426 * lxc_cmd_get_clone_flags: Get clone flags container was spawned with
428 * @name : name of container to connect to
429 * @lxcpath : the lxcpath in which the container is running
431 * Returns the clone flags on success, < 0 on failure
433 int lxc_cmd_get_clone_flags(const char *name
, const char *lxcpath
)
436 struct lxc_cmd_rr cmd
= {
437 .req
= { .cmd
= LXC_CMD_GET_CLONE_FLAGS
},
440 ret
= lxc_cmd(name
, &cmd
, &stopped
, lxcpath
, NULL
);
444 return PTR_TO_INT(cmd
.rsp
.data
);
447 static int lxc_cmd_get_clone_flags_callback(int fd
, struct lxc_cmd_req
*req
,
448 struct lxc_handler
*handler
)
450 struct lxc_cmd_rsp rsp
= { .data
= INT_TO_PTR(handler
->clone_flags
) };
452 return lxc_cmd_rsp_send(fd
, &rsp
);
456 * lxc_cmd_get_cgroup_path: Calculate a container's cgroup path for a
457 * particular subsystem. This is the cgroup path relative to the root
458 * of the cgroup filesystem.
460 * @name : name of container to connect to
461 * @lxcpath : the lxcpath in which the container is running
462 * @subsystem : the subsystem being asked about
464 * Returns the path on success, NULL on failure. The caller must free() the
467 char *lxc_cmd_get_cgroup_path(const char *name
, const char *lxcpath
,
468 const char *subsystem
)
471 struct lxc_cmd_rr cmd
= {
473 .cmd
= LXC_CMD_GET_CGROUP
,
474 .datalen
= strlen(subsystem
)+1,
479 ret
= lxc_cmd(name
, &cmd
, &stopped
, lxcpath
, NULL
);
481 TRACE("command %s failed for container \"%s\": %s.",
482 lxc_cmd_str(cmd
.req
.cmd
), name
, strerror(errno
));
487 WARN("container \"%s\" has stopped before sending its state", name
);
491 if (cmd
.rsp
.ret
< 0 || cmd
.rsp
.datalen
< 0) {
492 ERROR("command %s failed for container \"%s\": %s",
493 lxc_cmd_str(cmd
.req
.cmd
), name
, strerror(-cmd
.rsp
.ret
));
497 TRACE("command %s successful for container \"%s\"",
498 lxc_cmd_str(cmd
.req
.cmd
), name
);
503 static int lxc_cmd_get_cgroup_callback(int fd
, struct lxc_cmd_req
*req
,
504 struct lxc_handler
*handler
)
506 struct lxc_cmd_rsp rsp
;
509 if (req
->datalen
< 1)
512 path
= cgroup_get_cgroup(handler
, req
->data
);
515 rsp
.datalen
= strlen(path
) + 1,
516 rsp
.data
= (char *)path
;
519 return lxc_cmd_rsp_send(fd
, &rsp
);
523 * lxc_cmd_get_config_item: Get config item the running container
525 * @name : name of container to connect to
526 * @item : the configuration item to retrieve (ex: lxc.net.0.veth.pair)
527 * @lxcpath : the lxcpath in which the container is running
529 * Returns the item on success, NULL on failure. The caller must free() the
532 char *lxc_cmd_get_config_item(const char *name
, const char *item
,
536 struct lxc_cmd_rr cmd
= {
537 .req
= { .cmd
= LXC_CMD_GET_CONFIG_ITEM
,
539 .datalen
= strlen(item
)+1,
543 ret
= lxc_cmd(name
, &cmd
, &stopped
, lxcpath
, NULL
);
547 if (cmd
.rsp
.ret
== 0)
552 static int lxc_cmd_get_config_item_callback(int fd
, struct lxc_cmd_req
*req
,
553 struct lxc_handler
*handler
)
556 struct lxc_cmd_rsp rsp
;
558 struct lxc_config_t
*item
;
560 memset(&rsp
, 0, sizeof(rsp
));
561 item
= lxc_getconfig(req
->data
);
564 cilen
= item
->get(req
->data
, NULL
, 0, handler
->conf
, NULL
);
568 cidata
= alloca(cilen
+ 1);
569 if (item
->get(req
->data
, cidata
, cilen
+ 1, handler
->conf
, NULL
) != cilen
)
571 cidata
[cilen
] = '\0';
573 rsp
.datalen
= cilen
+ 1;
580 return lxc_cmd_rsp_send(fd
, &rsp
);
584 * lxc_cmd_get_state: Get current state of the container
586 * @name : name of container to connect to
587 * @lxcpath : the lxcpath in which the container is running
589 * Returns the state on success, < 0 on failure
591 int lxc_cmd_get_state(const char *name
, const char *lxcpath
)
594 struct lxc_cmd_rr cmd
= {
595 .req
= { .cmd
= LXC_CMD_GET_STATE
}
598 ret
= lxc_cmd(name
, &cmd
, &stopped
, lxcpath
, NULL
);
599 if (ret
< 0 && stopped
)
606 WARN("Container \"%s\" has stopped before sending its state.", name
);
610 DEBUG("Container \"%s\" is in \"%s\" state.", name
,
611 lxc_state2str(PTR_TO_INT(cmd
.rsp
.data
)));
612 return PTR_TO_INT(cmd
.rsp
.data
);
615 static int lxc_cmd_get_state_callback(int fd
, struct lxc_cmd_req
*req
,
616 struct lxc_handler
*handler
)
618 struct lxc_cmd_rsp rsp
= { .data
= INT_TO_PTR(handler
->state
) };
620 return lxc_cmd_rsp_send(fd
, &rsp
);
624 * lxc_cmd_stop: Stop the container previously started with lxc_start. All
625 * the processes running inside this container will be killed.
627 * @name : name of container to connect to
628 * @lxcpath : the lxcpath in which the container is running
630 * Returns 0 on success, < 0 on failure
632 int lxc_cmd_stop(const char *name
, const char *lxcpath
)
635 struct lxc_cmd_rr cmd
= {
636 .req
= { .cmd
= LXC_CMD_STOP
},
639 ret
= lxc_cmd(name
, &cmd
, &stopped
, lxcpath
, NULL
);
642 INFO("Container \"%s\" is already stopped.", name
);
648 /* we do not expect any answer, because we wait for the connection to be
652 ERROR("Failed to stop container \"%s\": %s.", name
,
653 strerror(-cmd
.rsp
.ret
));
657 INFO("Container \"%s\" has stopped.", name
);
661 static int lxc_cmd_stop_callback(int fd
, struct lxc_cmd_req
*req
,
662 struct lxc_handler
*handler
)
664 struct lxc_cmd_rsp rsp
;
665 int stopsignal
= SIGKILL
;
667 if (handler
->conf
->stopsignal
)
668 stopsignal
= handler
->conf
->stopsignal
;
669 memset(&rsp
, 0, sizeof(rsp
));
670 rsp
.ret
= kill(handler
->pid
, stopsignal
);
672 /* we can't just use lxc_unfreeze() since we are already in the
673 * context of handling the STOP cmd in lxc-start, and calling
674 * lxc_unfreeze() would do another cmd (GET_CGROUP) which would
677 if (cgroup_unfreeze(handler
))
679 ERROR("Failed to unfreeze container \"%s\".", handler
->name
);
683 return lxc_cmd_rsp_send(fd
, &rsp
);
687 * lxc_cmd_console_winch: To process as if a SIGWINCH were received
689 * @name : name of container to connect to
690 * @lxcpath : the lxcpath in which the container is running
692 * Returns 0 on success, < 0 on failure
694 int lxc_cmd_console_winch(const char *name
, const char *lxcpath
)
697 struct lxc_cmd_rr cmd
= {
698 .req
= { .cmd
= LXC_CMD_CONSOLE_WINCH
},
701 ret
= lxc_cmd(name
, &cmd
, &stopped
, lxcpath
, NULL
);
708 static int lxc_cmd_console_winch_callback(int fd
, struct lxc_cmd_req
*req
,
709 struct lxc_handler
*handler
)
711 struct lxc_cmd_rsp rsp
= { .data
= 0 };
713 lxc_console_sigwinch(SIGWINCH
);
714 return lxc_cmd_rsp_send(fd
, &rsp
);
718 * lxc_cmd_console: Open an fd to a tty in the container
720 * @name : name of container to connect to
721 * @ttynum : in: the tty to open or -1 for next available
722 * : out: the tty allocated
723 * @fd : out: file descriptor for master side of pty
724 * @lxcpath : the lxcpath in which the container is running
726 * Returns fd holding tty allocated on success, < 0 on failure
728 int lxc_cmd_console(const char *name
, int *ttynum
, int *fd
, const char *lxcpath
)
731 struct lxc_cmd_console_rsp_data
*rspdata
;
732 struct lxc_cmd_rr cmd
= {
733 .req
= { .cmd
= LXC_CMD_CONSOLE
, .data
= INT_TO_PTR(*ttynum
) },
736 ret
= lxc_cmd(name
, &cmd
, &stopped
, lxcpath
, NULL
);
740 if (cmd
.rsp
.ret
< 0) {
741 ERROR("Console access denied: %s.", strerror(-cmd
.rsp
.ret
));
747 ERROR("Console %d invalid, busy or all consoles busy.", *ttynum
);
752 rspdata
= cmd
.rsp
.data
;
753 if (rspdata
->masterfd
< 0) {
754 ERROR("Unable to allocate fd for tty %d.", rspdata
->ttynum
);
758 ret
= cmd
.rsp
.ret
; /* sock fd */
759 *fd
= rspdata
->masterfd
;
760 *ttynum
= rspdata
->ttynum
;
761 INFO("tty %d allocated fd %d sock %d.", rspdata
->ttynum
, *fd
, ret
);
767 static int lxc_cmd_console_callback(int fd
, struct lxc_cmd_req
*req
,
768 struct lxc_handler
*handler
)
770 int ttynum
= PTR_TO_INT(req
->data
);
772 struct lxc_cmd_rsp rsp
;
774 masterfd
= lxc_console_allocate(handler
->conf
, fd
, &ttynum
);
778 memset(&rsp
, 0, sizeof(rsp
));
779 rsp
.data
= INT_TO_PTR(ttynum
);
780 if (lxc_abstract_unix_send_fds(fd
, &masterfd
, 1, &rsp
, sizeof(rsp
)) < 0) {
781 ERROR("Failed to send tty to client.");
782 lxc_console_free(handler
->conf
, fd
);
789 /* special indicator to lxc_cmd_handler() to close the fd and do
796 * lxc_cmd_get_name: Returns the name of the container
798 * @hashed_sock_name: hashed socket name
800 * Returns the name on success, NULL on failure.
802 char *lxc_cmd_get_name(const char *hashed_sock_name
)
805 struct lxc_cmd_rr cmd
= {
806 .req
= { .cmd
= LXC_CMD_GET_NAME
},
809 ret
= lxc_cmd(NULL
, &cmd
, &stopped
, NULL
, hashed_sock_name
);
814 if (cmd
.rsp
.ret
== 0)
819 static int lxc_cmd_get_name_callback(int fd
, struct lxc_cmd_req
*req
,
820 struct lxc_handler
*handler
)
822 struct lxc_cmd_rsp rsp
;
824 memset(&rsp
, 0, sizeof(rsp
));
826 rsp
.data
= handler
->name
;
827 rsp
.datalen
= strlen(handler
->name
) + 1;
830 return lxc_cmd_rsp_send(fd
, &rsp
);
834 * lxc_cmd_get_lxcpath: Returns the lxcpath of the container
836 * @hashed_sock_name: hashed socket name
838 * Returns the lxcpath on success, NULL on failure.
840 char *lxc_cmd_get_lxcpath(const char *hashed_sock_name
)
843 struct lxc_cmd_rr cmd
= {
844 .req
= { .cmd
= LXC_CMD_GET_LXCPATH
},
847 ret
= lxc_cmd(NULL
, &cmd
, &stopped
, NULL
, hashed_sock_name
);
852 if (cmd
.rsp
.ret
== 0)
857 static int lxc_cmd_get_lxcpath_callback(int fd
, struct lxc_cmd_req
*req
,
858 struct lxc_handler
*handler
)
860 struct lxc_cmd_rsp rsp
;
862 memset(&rsp
, 0, sizeof(rsp
));
864 rsp
.data
= (char *)handler
->lxcpath
;
865 rsp
.datalen
= strlen(handler
->lxcpath
) + 1;
868 return lxc_cmd_rsp_send(fd
, &rsp
);
872 * lxc_cmd_state_server: register a client fd in the handler list
874 * @name : name of container to connect to
875 * @lxcpath : the lxcpath in which the container is running
877 * Returns the lxcpath on success, NULL on failure.
879 int lxc_cmd_state_server(const char *name
, const char *lxcpath
,
880 lxc_state_t states
[MAX_STATE
])
885 struct lxc_msg msg
= {0};
886 struct lxc_cmd_rr cmd
= {
888 .cmd
= LXC_CMD_STATE_SERVER
,
890 .datalen
= (sizeof(lxc_state_t
) * MAX_STATE
)
894 /* Lock the whole lxc_cmd_state_server_callback() call to ensure that
895 * lxc_set_state() doesn't cause us to miss a state.
898 /* Check if already in requested state. */
899 state
= lxc_getstate(name
, lxcpath
);
902 TRACE("failed to retrieve state of container: %s",
905 } else if (states
[state
]) {
907 TRACE("container is %s state", lxc_state2str(state
));
911 if ((state
== STARTING
) && !states
[RUNNING
] && !states
[STOPPING
] && !states
[STOPPED
]) {
913 TRACE("container is in %s state and caller requested to be "
914 "informed about a previous state",
915 lxc_state2str(state
));
917 } else if ((state
== RUNNING
) && !states
[STOPPING
] && !states
[STOPPED
]) {
919 TRACE("container is in %s state and caller requested to be "
920 "informed about a previous state",
921 lxc_state2str(state
));
923 } else if ((state
== STOPPING
) && !states
[STOPPED
]) {
925 TRACE("container is in %s state and caller requested to be "
926 "informed about a previous state",
927 lxc_state2str(state
));
929 } else if ((state
== STOPPED
) || (state
== ABORTING
)) {
931 TRACE("container is in %s state and caller requested to be "
932 "informed about a previous state",
933 lxc_state2str(state
));
937 ret
= lxc_cmd(name
, &cmd
, &stopped
, lxcpath
, NULL
);
940 ERROR("failed to execute command: %s", strerror(errno
));
943 /* We should now be guaranteed to get an answer from the state sending
947 if (cmd
.rsp
.ret
< 0) {
948 ERROR("failed to receive socket fd");
953 ret
= recv(cmd
.rsp
.ret
, &msg
, sizeof(msg
), 0);
958 ERROR("failed to receive message: %s", strerror(errno
));
962 ERROR("length of message was 0");
966 TRACE("received state %s from state client %d",
967 lxc_state2str(msg
.value
), cmd
.rsp
.ret
);
971 static int lxc_cmd_state_server_callback(int fd
, struct lxc_cmd_req
*req
,
972 struct lxc_handler
*handler
)
974 struct lxc_cmd_rsp rsp
= {0};
975 struct state_client
*newclient
;
976 struct lxc_list
*tmplist
;
978 if (req
->datalen
< 0) {
979 TRACE("requested datalen was < 0");
984 TRACE("no states requested");
988 newclient
= malloc(sizeof(*newclient
));
992 /* copy requested states */
993 memcpy(newclient
->states
, req
->data
, sizeof(newclient
->states
));
994 newclient
->clientfd
= fd
;
996 tmplist
= malloc(sizeof(*tmplist
));
1002 lxc_list_add_elem(tmplist
, newclient
);
1003 lxc_list_add_tail(&handler
->state_clients
, tmplist
);
1005 TRACE("added state client %d to state client list", fd
);
1007 return lxc_cmd_rsp_send(fd
, &rsp
);
1010 static int lxc_cmd_process(int fd
, struct lxc_cmd_req
*req
,
1011 struct lxc_handler
*handler
)
1013 typedef int (*callback
)(int, struct lxc_cmd_req
*, struct lxc_handler
*);
1015 callback cb
[LXC_CMD_MAX
] = {
1016 [LXC_CMD_CONSOLE
] = lxc_cmd_console_callback
,
1017 [LXC_CMD_CONSOLE_WINCH
] = lxc_cmd_console_winch_callback
,
1018 [LXC_CMD_STOP
] = lxc_cmd_stop_callback
,
1019 [LXC_CMD_GET_STATE
] = lxc_cmd_get_state_callback
,
1020 [LXC_CMD_GET_INIT_PID
] = lxc_cmd_get_init_pid_callback
,
1021 [LXC_CMD_GET_CLONE_FLAGS
] = lxc_cmd_get_clone_flags_callback
,
1022 [LXC_CMD_GET_CGROUP
] = lxc_cmd_get_cgroup_callback
,
1023 [LXC_CMD_GET_CONFIG_ITEM
] = lxc_cmd_get_config_item_callback
,
1024 [LXC_CMD_GET_NAME
] = lxc_cmd_get_name_callback
,
1025 [LXC_CMD_GET_LXCPATH
] = lxc_cmd_get_lxcpath_callback
,
1026 [LXC_CMD_STATE_SERVER
] = lxc_cmd_state_server_callback
,
1029 if (req
->cmd
>= LXC_CMD_MAX
) {
1030 ERROR("Undefined command id %d received.", req
->cmd
);
1033 return cb
[req
->cmd
](fd
, req
, handler
);
1036 static void lxc_cmd_fd_cleanup(int fd
, struct lxc_handler
*handler
,
1037 struct lxc_epoll_descr
*descr
)
1039 lxc_console_free(handler
->conf
, fd
);
1040 lxc_mainloop_del_handler(descr
, fd
);
1044 static int lxc_cmd_handler(int fd
, uint32_t events
, void *data
,
1045 struct lxc_epoll_descr
*descr
)
1048 struct lxc_cmd_req req
;
1049 struct lxc_handler
*handler
= data
;
1051 ret
= lxc_abstract_unix_rcv_credential(fd
, &req
, sizeof(req
));
1052 if (ret
== -EACCES
) {
1053 /* we don't care for the peer, just send and close */
1054 struct lxc_cmd_rsp rsp
= { .ret
= ret
};
1056 lxc_cmd_rsp_send(fd
, &rsp
);
1061 SYSERROR("Failed to receive data on command socket.");
1066 DEBUG("Peer has disconnected.");
1070 if (ret
!= sizeof(req
)) {
1071 WARN("Failed to receive full command request. Ignoring request.");
1076 if (req
.datalen
> LXC_CMD_DATA_MAX
) {
1077 ERROR("Received command data length %d is too large.", req
.datalen
);
1082 if (req
.datalen
> 0) {
1085 reqdata
= alloca(req
.datalen
);
1086 ret
= recv(fd
, reqdata
, req
.datalen
, 0);
1087 if (ret
!= req
.datalen
) {
1088 WARN("Failed to receive full command request. Ignoring request.");
1095 ret
= lxc_cmd_process(fd
, &req
, handler
);
1097 /* this is not an error, but only a request to close fd */
1105 lxc_cmd_fd_cleanup(fd
, handler
, descr
);
1109 static int lxc_cmd_accept(int fd
, uint32_t events
, void *data
,
1110 struct lxc_epoll_descr
*descr
)
1112 int opt
= 1, ret
= -1, connection
;
1114 connection
= accept(fd
, NULL
, 0);
1115 if (connection
< 0) {
1116 SYSERROR("Failed to accept connection to run command.");
1120 if (fcntl(connection
, F_SETFD
, FD_CLOEXEC
)) {
1121 SYSERROR("Failed to set close-on-exec on incoming command connection.");
1125 if (setsockopt(connection
, SOL_SOCKET
,
1126 SO_PASSCRED
, &opt
, sizeof(opt
))) {
1127 SYSERROR("Failed to enable necessary credentials on command socket.");
1131 ret
= lxc_mainloop_add_handler(descr
, connection
, lxc_cmd_handler
, data
);
1133 ERROR("Failed to add command handler.");
1145 int lxc_cmd_init(const char *name
, struct lxc_handler
*handler
,
1146 const char *lxcpath
)
1149 char path
[sizeof(((struct sockaddr_un
*)0)->sun_path
)] = { 0 };
1150 char *offset
= &path
[1];
1153 /* -2 here because this is an abstract unix socket so it needs a
1154 * leading \0, and we null terminate, so it needs a trailing \0.
1155 * Although null termination isn't required by the API, we do it anyway
1156 * because we print the sockname out sometimes.
1158 len
= sizeof(path
) - 2;
1159 if (fill_sock_name(offset
, len
, name
, lxcpath
, NULL
))
1162 fd
= lxc_abstract_unix_open(path
, SOCK_STREAM
, 0);
1164 ERROR("Failed to create the command service point %s: %s.",
1165 offset
, strerror(errno
));
1166 if (errno
== EADDRINUSE
)
1167 ERROR("Container \"%s\" appears to be already running!", name
);
1171 if (fcntl(fd
, F_SETFD
, FD_CLOEXEC
)) {
1172 SYSERROR("Failed to set FD_CLOEXEC on signal file descriptor.");
1177 handler
->conf
->maincmd_fd
= fd
;
1181 int lxc_cmd_mainloop_add(const char *name
,
1182 struct lxc_epoll_descr
*descr
,
1183 struct lxc_handler
*handler
)
1185 int ret
, fd
= handler
->conf
->maincmd_fd
;
1187 ret
= lxc_mainloop_add_handler(descr
, fd
, lxc_cmd_accept
, handler
);
1189 ERROR("Failed to add handler for command socket.");