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 */
51 * This file provides the different functions for clients to
52 * query/command the server. The client is typically some lxc
53 * tool and the server is typically the container (ie. lxc-start).
55 * Each command is transactional, the clients send a request to
56 * the server and the server answers the request with a message
57 * giving the request's status (zero or a negative errno value).
58 * Both the request and response may contain additional data.
60 * Each command is wrapped in a ancillary message in order to pass
61 * a credential making possible to the server to check if the client
62 * is allowed to ask for this command or not.
64 * IMPORTANTLY: Note that semantics for current commands are fixed. If you
65 * wish to make any changes to how, say, LXC_CMD_GET_CONFIG_ITEM works by
66 * adding information to the end of cmd.data, then you must introduce a new
67 * LXC_CMD_GET_CONFIG_ITEM_V2 define with a new number. You may wish to
68 * also mark LXC_CMD_GET_CONFIG_ITEM deprecated in commands.h.
70 * This is necessary in order to avoid having a newly compiled lxc command
71 * communicating with a running (old) monitor from crashing the running
75 lxc_log_define(lxc_commands
, lxc
);
77 static int fill_sock_name(char *path
, int len
, const char *name
,
78 const char *lxcpath
, const char *hashed_sock_name
)
85 if (hashed_sock_name
!= NULL
) {
86 ret
= snprintf(path
, len
, "lxc/%s/command", hashed_sock_name
);
87 if (ret
< 0 || ret
>= len
) {
88 ERROR("Error writing to command sock path");
95 lxcpath
= lxc_global_config_value("lxc.lxcpath");
97 ERROR("Out of memory getting lxcpath");
102 ret
= snprintf(path
, len
, "%s/%s/command", lxcpath
, name
);
104 ERROR("Error writing to command sock path");
110 /* ret >= len; lxcpath or name is too long. hash both */
111 tmplen
= strlen(name
) + strlen(lxcpath
) + 2;
112 tmppath
= alloca(tmplen
);
113 ret
= snprintf(tmppath
, tmplen
, "%s/%s", lxcpath
, name
);
114 if (ret
< 0 || ret
>= tmplen
) {
115 ERROR("memory error");
118 hash
= fnv_64a_buf(tmppath
, ret
, FNV1A_64_INIT
);
119 ret
= snprintf(path
, len
, "lxc/%016" PRIx64
"/command", hash
);
120 if (ret
< 0 || ret
>= len
) {
121 ERROR("Command socket name too long");
128 static const char *lxc_cmd_str(lxc_cmd_t cmd
)
130 static const char * const cmdname
[LXC_CMD_MAX
] = {
131 [LXC_CMD_CONSOLE
] = "console",
132 [LXC_CMD_STOP
] = "stop",
133 [LXC_CMD_GET_STATE
] = "get_state",
134 [LXC_CMD_GET_INIT_PID
] = "get_init_pid",
135 [LXC_CMD_GET_CLONE_FLAGS
] = "get_clone_flags",
136 [LXC_CMD_GET_CGROUP
] = "get_cgroup",
137 [LXC_CMD_GET_CONFIG_ITEM
] = "get_config_item",
138 [LXC_CMD_GET_NAME
] = "get_name",
139 [LXC_CMD_GET_LXCPATH
] = "get_lxcpath",
142 if (cmd
>= LXC_CMD_MAX
)
143 return "Unknown cmd";
148 * lxc_cmd_rsp_recv: Receive a response to a command
150 * @sock : the socket connected to the container
151 * @cmd : command to put response in
153 * Returns the size of the response message or < 0 on failure
155 * Note that if the command response datalen > 0, then data is
156 * a malloc()ed buffer and should be free()ed by the caller. If
157 * the response data is <= a void * worth of data, it will be
158 * stored directly in data and datalen will be 0.
160 * As a special case, the response for LXC_CMD_CONSOLE is created
161 * here as it contains an fd for the master pty passed through the
164 static int lxc_cmd_rsp_recv(int sock
, struct lxc_cmd_rr
*cmd
)
167 struct lxc_cmd_rsp
*rsp
= &cmd
->rsp
;
169 ret
= lxc_abstract_unix_recv_fd(sock
, &rspfd
, rsp
, sizeof(*rsp
));
171 WARN("command %s failed to receive response",
172 lxc_cmd_str(cmd
->req
.cmd
));
176 if (cmd
->req
.cmd
== LXC_CMD_CONSOLE
) {
177 struct lxc_cmd_console_rsp_data
*rspdata
;
179 /* recv() returns 0 bytes when a tty cannot be allocated,
180 * rsp->ret is < 0 when the peer permission check failed
182 if (ret
== 0 || rsp
->ret
< 0)
185 rspdata
= malloc(sizeof(*rspdata
));
187 ERROR("command %s couldn't allocate response buffer",
188 lxc_cmd_str(cmd
->req
.cmd
));
191 rspdata
->masterfd
= rspfd
;
192 rspdata
->ttynum
= PTR_TO_INT(rsp
->data
);
196 if (rsp
->datalen
== 0)
198 if (rsp
->datalen
> LXC_CMD_DATA_MAX
) {
199 ERROR("command %s response data %d too long",
200 lxc_cmd_str(cmd
->req
.cmd
), rsp
->datalen
);
205 rsp
->data
= malloc(rsp
->datalen
);
207 ERROR("command %s unable to allocate response buffer",
208 lxc_cmd_str(cmd
->req
.cmd
));
211 ret
= recv(sock
, rsp
->data
, rsp
->datalen
, 0);
212 if (ret
!= rsp
->datalen
) {
213 ERROR("command %s failed to receive response data",
214 lxc_cmd_str(cmd
->req
.cmd
));
223 * lxc_cmd_rsp_send: Send a command response
225 * @fd : file descriptor of socket to send response on
226 * @rsp : response to send
228 * Returns 0 on success, < 0 on failure
230 static int lxc_cmd_rsp_send(int fd
, struct lxc_cmd_rsp
*rsp
)
234 ret
= send(fd
, rsp
, sizeof(*rsp
), 0);
235 if (ret
!= sizeof(*rsp
)) {
236 ERROR("failed to send command response %d %s", ret
,
241 if (rsp
->datalen
> 0) {
242 ret
= send(fd
, rsp
->data
, rsp
->datalen
, 0);
243 if (ret
!= rsp
->datalen
) {
244 WARN("failed to send command response data %d %s", ret
,
253 * lxc_cmd: Connect to the specified running container, send it a command
254 * request and collect the response
256 * @name : name of container to connect to
257 * @cmd : command with initialized reqest to send
258 * @stopped : output indicator if the container was not running
259 * @lxcpath : the lxcpath in which the container is running
261 * Returns the size of the response message on success, < 0 on failure
263 * Note that there is a special case for LXC_CMD_CONSOLE. For this command
264 * the fd cannot be closed because it is used as a placeholder to indicate
265 * that a particular tty slot is in use. The fd is also used as a signal to
266 * the container that when the caller dies or closes the fd, the container
267 * will notice the fd on its side of the socket in its mainloop select and
268 * then free the slot with lxc_cmd_fd_cleanup(). The socket fd will be
269 * returned in the cmd response structure.
271 static int lxc_cmd(const char *name
, struct lxc_cmd_rr
*cmd
, int *stopped
,
272 const char *lxcpath
, const char *hashed_sock_name
)
275 char path
[sizeof(((struct sockaddr_un
*)0)->sun_path
)] = { 0 };
276 char *offset
= &path
[1];
278 int stay_connected
= cmd
->req
.cmd
== LXC_CMD_CONSOLE
;
282 len
= sizeof(path
)-1;
283 if (fill_sock_name(offset
, len
, name
, lxcpath
, hashed_sock_name
))
286 sock
= lxc_abstract_unix_connect(path
);
288 if (errno
== ECONNREFUSED
)
291 SYSERROR("command %s failed to connect to '@%s'",
292 lxc_cmd_str(cmd
->req
.cmd
), offset
);
296 ret
= lxc_abstract_unix_send_credential(sock
, &cmd
->req
, sizeof(cmd
->req
));
297 if (ret
!= sizeof(cmd
->req
)) {
300 SYSERROR("command %s failed to send req to '@%s' %d",
301 lxc_cmd_str(cmd
->req
.cmd
), offset
, ret
);
307 if (cmd
->req
.datalen
> 0) {
308 ret
= send(sock
, cmd
->req
.data
, cmd
->req
.datalen
, MSG_NOSIGNAL
);
309 if (ret
!= cmd
->req
.datalen
) {
312 SYSERROR("command %s failed to send request data to '@%s' %d",
313 lxc_cmd_str(cmd
->req
.cmd
), offset
, ret
);
320 ret
= lxc_cmd_rsp_recv(sock
, cmd
);
322 if (!stay_connected
|| ret
<= 0)
324 if (stay_connected
&& ret
> 0)
335 int lxc_try_cmd(const char *name
, const char *lxcpath
)
338 struct lxc_cmd_rr cmd
= {
339 .req
= { .cmd
= LXC_CMD_GET_INIT_PID
},
342 ret
= lxc_cmd(name
, &cmd
, &stopped
, lxcpath
, NULL
);
346 if (ret
> 0 && cmd
.rsp
.ret
< 0) {
354 * At this point we weren't denied access, and the
355 * container *was* started. There was some inexplicable
356 * error in the protocol.
357 * I'm not clear on whether we should return -1 here, but
358 * we didn't receive a -EACCES, so technically it's not that
359 * we're not allowed to control the container - it's just not
365 /* Implentations of the commands and their callbacks */
368 * lxc_cmd_get_init_pid: Get pid of the container's init process
370 * @name : name of container to connect to
371 * @lxcpath : the lxcpath in which the container is running
373 * Returns the pid on success, < 0 on failure
375 pid_t
lxc_cmd_get_init_pid(const char *name
, const char *lxcpath
)
378 struct lxc_cmd_rr cmd
= {
379 .req
= { .cmd
= LXC_CMD_GET_INIT_PID
},
382 ret
= lxc_cmd(name
, &cmd
, &stopped
, lxcpath
, NULL
);
386 return PTR_TO_INT(cmd
.rsp
.data
);
389 static int lxc_cmd_get_init_pid_callback(int fd
, struct lxc_cmd_req
*req
,
390 struct lxc_handler
*handler
)
392 struct lxc_cmd_rsp rsp
= { .data
= INT_TO_PTR(handler
->pid
) };
394 return lxc_cmd_rsp_send(fd
, &rsp
);
398 * lxc_cmd_get_clone_flags: Get clone flags container was spawned with
400 * @name : name of container to connect to
401 * @lxcpath : the lxcpath in which the container is running
403 * Returns the clone flags on success, < 0 on failure
405 int lxc_cmd_get_clone_flags(const char *name
, const char *lxcpath
)
408 struct lxc_cmd_rr cmd
= {
409 .req
= { .cmd
= LXC_CMD_GET_CLONE_FLAGS
},
412 ret
= lxc_cmd(name
, &cmd
, &stopped
, lxcpath
, NULL
);
416 return PTR_TO_INT(cmd
.rsp
.data
);
419 static int lxc_cmd_get_clone_flags_callback(int fd
, struct lxc_cmd_req
*req
,
420 struct lxc_handler
*handler
)
422 struct lxc_cmd_rsp rsp
= { .data
= INT_TO_PTR(handler
->clone_flags
) };
424 return lxc_cmd_rsp_send(fd
, &rsp
);
428 * lxc_cmd_get_cgroup_path: Calculate a container's cgroup path for a
429 * particular subsystem. This is the cgroup path relative to the root
430 * of the cgroup filesystem.
432 * @name : name of container to connect to
433 * @lxcpath : the lxcpath in which the container is running
434 * @subsystem : the subsystem being asked about
436 * Returns the path on success, NULL on failure. The caller must free() the
439 char *lxc_cmd_get_cgroup_path(const char *name
, const char *lxcpath
,
440 const char *subsystem
)
443 struct lxc_cmd_rr cmd
= {
445 .cmd
= LXC_CMD_GET_CGROUP
,
446 .datalen
= strlen(subsystem
)+1,
451 ret
= lxc_cmd(name
, &cmd
, &stopped
, lxcpath
, NULL
);
456 WARN("'%s' has stopped before sending its state", name
);
460 if (cmd
.rsp
.ret
< 0 || cmd
.rsp
.datalen
< 0) {
461 ERROR("command %s failed for '%s': %s",
462 lxc_cmd_str(cmd
.req
.cmd
), name
,
463 strerror(-cmd
.rsp
.ret
));
470 static int lxc_cmd_get_cgroup_callback(int fd
, struct lxc_cmd_req
*req
,
471 struct lxc_handler
*handler
)
473 struct lxc_cmd_rsp rsp
;
476 if (req
->datalen
< 1)
479 path
= cgroup_get_cgroup(handler
, req
->data
);
482 rsp
.datalen
= strlen(path
) + 1,
483 rsp
.data
= (char *)path
;
486 return lxc_cmd_rsp_send(fd
, &rsp
);
490 * lxc_cmd_get_config_item: Get config item the running container
492 * @name : name of container to connect to
493 * @item : the configuration item to retrieve (ex: lxc.network.0.veth.pair)
494 * @lxcpath : the lxcpath in which the container is running
496 * Returns the item on success, NULL on failure. The caller must free() the
499 char *lxc_cmd_get_config_item(const char *name
, const char *item
,
503 struct lxc_cmd_rr cmd
= {
504 .req
= { .cmd
= LXC_CMD_GET_CONFIG_ITEM
,
506 .datalen
= strlen(item
)+1,
510 ret
= lxc_cmd(name
, &cmd
, &stopped
, lxcpath
, NULL
);
514 if (cmd
.rsp
.ret
== 0)
519 static int lxc_cmd_get_config_item_callback(int fd
, struct lxc_cmd_req
*req
,
520 struct lxc_handler
*handler
)
523 struct lxc_cmd_rsp rsp
;
526 memset(&rsp
, 0, sizeof(rsp
));
527 cilen
= lxc_get_config_item(handler
->conf
, req
->data
, NULL
, 0);
531 cidata
= alloca(cilen
+ 1);
532 if (lxc_get_config_item(handler
->conf
, req
->data
, cidata
, cilen
+ 1) != cilen
)
534 cidata
[cilen
] = '\0';
536 rsp
.datalen
= cilen
+ 1;
543 return lxc_cmd_rsp_send(fd
, &rsp
);
547 * lxc_cmd_get_state: Get current state of the container
549 * @name : name of container to connect to
550 * @lxcpath : the lxcpath in which the container is running
552 * Returns the state on success, < 0 on failure
554 lxc_state_t
lxc_cmd_get_state(const char *name
, const char *lxcpath
)
557 struct lxc_cmd_rr cmd
= {
558 .req
= { .cmd
= LXC_CMD_GET_STATE
}
561 ret
= lxc_cmd(name
, &cmd
, &stopped
, lxcpath
, NULL
);
562 if (ret
< 0 && stopped
)
569 WARN("'%s' has stopped before sending its state", name
);
573 DEBUG("'%s' is in '%s' state", name
,
574 lxc_state2str(PTR_TO_INT(cmd
.rsp
.data
)));
575 return PTR_TO_INT(cmd
.rsp
.data
);
578 static int lxc_cmd_get_state_callback(int fd
, struct lxc_cmd_req
*req
,
579 struct lxc_handler
*handler
)
581 struct lxc_cmd_rsp rsp
= { .data
= INT_TO_PTR(handler
->state
) };
583 return lxc_cmd_rsp_send(fd
, &rsp
);
587 * lxc_cmd_stop: Stop the container previously started with lxc_start. All
588 * the processes running inside this container will be killed.
590 * @name : name of container to connect to
591 * @lxcpath : the lxcpath in which the container is running
593 * Returns 0 on success, < 0 on failure
595 int lxc_cmd_stop(const char *name
, const char *lxcpath
)
598 struct lxc_cmd_rr cmd
= {
599 .req
= { .cmd
= LXC_CMD_STOP
},
602 ret
= lxc_cmd(name
, &cmd
, &stopped
, lxcpath
, NULL
);
605 INFO("'%s' is already stopped", name
);
611 /* we do not expect any answer, because we wait for the connection to be
615 ERROR("failed to stop '%s': %s", name
, strerror(-cmd
.rsp
.ret
));
619 INFO("'%s' has stopped", name
);
623 static int lxc_cmd_stop_callback(int fd
, struct lxc_cmd_req
*req
,
624 struct lxc_handler
*handler
)
626 struct lxc_cmd_rsp rsp
;
627 int stopsignal
= SIGKILL
;
629 if (handler
->conf
->stopsignal
)
630 stopsignal
= handler
->conf
->stopsignal
;
631 memset(&rsp
, 0, sizeof(rsp
));
632 rsp
.ret
= kill(handler
->pid
, stopsignal
);
634 /* we can't just use lxc_unfreeze() since we are already in the
635 * context of handling the STOP cmd in lxc-start, and calling
636 * lxc_unfreeze() would do another cmd (GET_CGROUP) which would
639 if (cgroup_unfreeze(handler
))
641 ERROR("Failed to unfreeze %s:%s", handler
->lxcpath
, handler
->name
);
645 return lxc_cmd_rsp_send(fd
, &rsp
);
649 * lxc_cmd_console_winch: To process as if a SIGWINCH were received
651 * @name : name of container to connect to
652 * @lxcpath : the lxcpath in which the container is running
654 * Returns 0 on success, < 0 on failure
656 int lxc_cmd_console_winch(const char *name
, const char *lxcpath
)
659 struct lxc_cmd_rr cmd
= {
660 .req
= { .cmd
= LXC_CMD_CONSOLE_WINCH
},
663 ret
= lxc_cmd(name
, &cmd
, &stopped
, lxcpath
, NULL
);
670 static int lxc_cmd_console_winch_callback(int fd
, struct lxc_cmd_req
*req
,
671 struct lxc_handler
*handler
)
673 struct lxc_cmd_rsp rsp
= { .data
= 0 };
675 lxc_console_sigwinch(SIGWINCH
);
676 return lxc_cmd_rsp_send(fd
, &rsp
);
680 * lxc_cmd_console: Open an fd to a tty in the container
682 * @name : name of container to connect to
683 * @ttynum : in: the tty to open or -1 for next available
684 * : out: the tty allocated
685 * @fd : out: file descriptor for master side of pty
686 * @lxcpath : the lxcpath in which the container is running
688 * Returns fd holding tty allocated on success, < 0 on failure
690 int lxc_cmd_console(const char *name
, int *ttynum
, int *fd
, const char *lxcpath
)
693 struct lxc_cmd_console_rsp_data
*rspdata
;
694 struct lxc_cmd_rr cmd
= {
695 .req
= { .cmd
= LXC_CMD_CONSOLE
, .data
= INT_TO_PTR(*ttynum
) },
698 ret
= lxc_cmd(name
, &cmd
, &stopped
, lxcpath
, NULL
);
702 if (cmd
.rsp
.ret
< 0) {
703 ERROR("console access denied: %s", strerror(-cmd
.rsp
.ret
));
709 ERROR("console %d invalid,busy or all consoles busy", *ttynum
);
714 rspdata
= cmd
.rsp
.data
;
715 if (rspdata
->masterfd
< 0) {
716 ERROR("unable to allocate fd for tty %d", rspdata
->ttynum
);
720 ret
= cmd
.rsp
.ret
; /* sock fd */
721 *fd
= rspdata
->masterfd
;
722 *ttynum
= rspdata
->ttynum
;
723 INFO("tty %d allocated fd %d sock %d", rspdata
->ttynum
, *fd
, ret
);
729 static int lxc_cmd_console_callback(int fd
, struct lxc_cmd_req
*req
,
730 struct lxc_handler
*handler
)
732 int ttynum
= PTR_TO_INT(req
->data
);
734 struct lxc_cmd_rsp rsp
;
736 masterfd
= lxc_console_allocate(handler
->conf
, fd
, &ttynum
);
740 memset(&rsp
, 0, sizeof(rsp
));
741 rsp
.data
= INT_TO_PTR(ttynum
);
742 if (lxc_abstract_unix_send_fd(fd
, masterfd
, &rsp
, sizeof(rsp
)) < 0) {
743 ERROR("failed to send tty to client");
744 lxc_console_free(handler
->conf
, fd
);
751 /* special indicator to lxc_cmd_handler() to close the fd and do
758 * lxc_cmd_get_name: Returns the name of the container
760 * @hashed_sock_name: hashed socket name
762 * Returns the name on success, NULL on failure.
764 char *lxc_cmd_get_name(const char *hashed_sock_name
)
767 struct lxc_cmd_rr cmd
= {
768 .req
= { .cmd
= LXC_CMD_GET_NAME
},
771 ret
= lxc_cmd(NULL
, &cmd
, &stopped
, NULL
, hashed_sock_name
);
776 if (cmd
.rsp
.ret
== 0)
781 static int lxc_cmd_get_name_callback(int fd
, struct lxc_cmd_req
*req
,
782 struct lxc_handler
*handler
)
784 struct lxc_cmd_rsp rsp
;
786 memset(&rsp
, 0, sizeof(rsp
));
788 rsp
.data
= handler
->name
;
789 rsp
.datalen
= strlen(handler
->name
) + 1;
792 return lxc_cmd_rsp_send(fd
, &rsp
);
796 * lxc_cmd_get_lxcpath: Returns the lxcpath of the container
798 * @hashed_sock_name: hashed socket name
800 * Returns the lxcpath on success, NULL on failure.
802 char *lxc_cmd_get_lxcpath(const char *hashed_sock_name
)
805 struct lxc_cmd_rr cmd
= {
806 .req
= { .cmd
= LXC_CMD_GET_LXCPATH
},
809 ret
= lxc_cmd(NULL
, &cmd
, &stopped
, NULL
, hashed_sock_name
);
814 if (cmd
.rsp
.ret
== 0)
819 static int lxc_cmd_get_lxcpath_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
= (char *)handler
->lxcpath
;
827 rsp
.datalen
= strlen(handler
->lxcpath
) + 1;
830 return lxc_cmd_rsp_send(fd
, &rsp
);
833 static int lxc_cmd_process(int fd
, struct lxc_cmd_req
*req
,
834 struct lxc_handler
*handler
)
836 typedef int (*callback
)(int, struct lxc_cmd_req
*, struct lxc_handler
*);
838 callback cb
[LXC_CMD_MAX
] = {
839 [LXC_CMD_CONSOLE
] = lxc_cmd_console_callback
,
840 [LXC_CMD_CONSOLE_WINCH
] = lxc_cmd_console_winch_callback
,
841 [LXC_CMD_STOP
] = lxc_cmd_stop_callback
,
842 [LXC_CMD_GET_STATE
] = lxc_cmd_get_state_callback
,
843 [LXC_CMD_GET_INIT_PID
] = lxc_cmd_get_init_pid_callback
,
844 [LXC_CMD_GET_CLONE_FLAGS
] = lxc_cmd_get_clone_flags_callback
,
845 [LXC_CMD_GET_CGROUP
] = lxc_cmd_get_cgroup_callback
,
846 [LXC_CMD_GET_CONFIG_ITEM
] = lxc_cmd_get_config_item_callback
,
847 [LXC_CMD_GET_NAME
] = lxc_cmd_get_name_callback
,
848 [LXC_CMD_GET_LXCPATH
] = lxc_cmd_get_lxcpath_callback
,
851 if (req
->cmd
>= LXC_CMD_MAX
) {
852 ERROR("bad cmd %d received", req
->cmd
);
855 return cb
[req
->cmd
](fd
, req
, handler
);
858 static void lxc_cmd_fd_cleanup(int fd
, struct lxc_handler
*handler
,
859 struct lxc_epoll_descr
*descr
)
861 lxc_console_free(handler
->conf
, fd
);
862 lxc_mainloop_del_handler(descr
, fd
);
866 static int lxc_cmd_handler(int fd
, uint32_t events
, void *data
,
867 struct lxc_epoll_descr
*descr
)
870 struct lxc_cmd_req req
;
871 struct lxc_handler
*handler
= data
;
873 ret
= lxc_abstract_unix_rcv_credential(fd
, &req
, sizeof(req
));
874 if (ret
== -EACCES
) {
875 /* we don't care for the peer, just send and close */
876 struct lxc_cmd_rsp rsp
= { .ret
= ret
};
878 lxc_cmd_rsp_send(fd
, &rsp
);
883 SYSERROR("failed to receive data on command socket");
888 DEBUG("peer has disconnected");
892 if (ret
!= sizeof(req
)) {
893 WARN("partial request, ignored");
898 if (req
.datalen
> LXC_CMD_DATA_MAX
) {
899 ERROR("cmd data length %d too large", req
.datalen
);
904 if (req
.datalen
> 0) {
907 reqdata
= alloca(req
.datalen
);
908 ret
= recv(fd
, reqdata
, req
.datalen
, 0);
909 if (ret
!= req
.datalen
) {
910 WARN("partial request, ignored");
917 ret
= lxc_cmd_process(fd
, &req
, handler
);
919 /* this is not an error, but only a request to close fd */
927 lxc_cmd_fd_cleanup(fd
, handler
, descr
);
931 static int lxc_cmd_accept(int fd
, uint32_t events
, void *data
,
932 struct lxc_epoll_descr
*descr
)
934 int opt
= 1, ret
= -1, connection
;
936 connection
= accept(fd
, NULL
, 0);
937 if (connection
< 0) {
938 SYSERROR("failed to accept connection");
942 if (fcntl(connection
, F_SETFD
, FD_CLOEXEC
)) {
943 SYSERROR("failed to set close-on-exec on incoming connection");
947 if (setsockopt(connection
, SOL_SOCKET
,
948 SO_PASSCRED
, &opt
, sizeof(opt
))) {
949 SYSERROR("failed to enable credential on socket");
953 ret
= lxc_mainloop_add_handler(descr
, connection
, lxc_cmd_handler
, data
);
955 ERROR("failed to add handler");
967 int lxc_cmd_init(const char *name
, struct lxc_handler
*handler
,
971 char path
[sizeof(((struct sockaddr_un
*)0)->sun_path
)] = { 0 };
972 char *offset
= &path
[1];
975 len
= sizeof(path
)-1;
976 if (fill_sock_name(offset
, len
, name
, lxcpath
, NULL
))
979 fd
= lxc_abstract_unix_open(path
, SOCK_STREAM
, 0);
981 ERROR("failed (%d) to create the command service point %s", errno
, offset
);
982 if (errno
== EADDRINUSE
) {
984 ERROR("# The container appears to be already running!");
990 if (fcntl(fd
, F_SETFD
, FD_CLOEXEC
)) {
991 SYSERROR("failed to set sigfd to close-on-exec");
996 handler
->conf
->maincmd_fd
= fd
;
1000 int lxc_cmd_mainloop_add(const char *name
,
1001 struct lxc_epoll_descr
*descr
,
1002 struct lxc_handler
*handler
)
1004 int ret
, fd
= handler
->conf
->maincmd_fd
;
1006 ret
= lxc_mainloop_add_handler(descr
, fd
, lxc_cmd_accept
, handler
);
1008 ERROR("failed to add handler for command socket");