]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/commands.c
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include <sys/socket.h>
32 #include <sys/param.h>
38 #include <lxc/start.h> /* for struct lxc_handler */
39 #include <lxc/utils.h>
47 * This file provides the different functions to have the client
48 * and the server to communicate
50 * Each command is transactional, the client send a request to
51 * the server and the server answer the request with a message
52 * giving the request's status (zero or a negative errno value).
54 * Each command is wrapped in a ancillary message in order to pass
55 * a credential making possible to the server to check if the client
56 * is allowed to ask for this command or not.
60 lxc_log_define(lxc_commands
, lxc
);
62 static int fill_sock_name(char *path
, int len
, const char *name
,
65 const char *lxcpath
= NULL
;
69 lxcpath
= default_lxc_path();
71 ERROR("Out of memory getting lxcpath");
75 ret
= snprintf(path
, len
, "%s/%s/command", lxcpath
? lxcpath
: inpath
, name
);
77 if (ret
< 0 || ret
>= len
) {
78 ERROR("Name too long");
84 static int receive_answer(int sock
, struct lxc_answer
*answer
)
87 static char answerpath
[MAXPATHLEN
];
89 ret
= lxc_af_unix_recv_fd(sock
, &answer
->fd
, answer
, sizeof(*answer
));
91 ERROR("failed to receive answer for the command");
92 if (answer
->pathlen
== 0)
94 if (answer
->pathlen
>= MAXPATHLEN
) {
95 ERROR("cgroup path was too long");
98 ret
= recv(sock
, answerpath
, answer
->pathlen
, 0);
99 if (ret
!= answer
->pathlen
) {
100 ERROR("failed to receive answer for the command");
103 answer
->path
= answerpath
;
108 static int __lxc_command(const char *name
, struct lxc_command
*command
,
109 int *stopped
, int stay_connected
, const char *lxcpath
)
112 char path
[sizeof(((struct sockaddr_un
*)0)->sun_path
)] = { 0 };
113 char *offset
= &path
[1];
116 len
= sizeof(path
)-1;
117 if (fill_sock_name(offset
, len
, name
, lxcpath
))
120 sock
= lxc_af_unix_connect(path
);
121 if (sock
< 0 && errno
== ECONNREFUSED
) {
127 SYSERROR("failed to connect to '@%s'", offset
);
131 ret
= lxc_af_unix_send_credential(sock
, &command
->request
,
132 sizeof(command
->request
));
134 SYSERROR("failed to send request to '@%s'", offset
);
138 if (ret
!= sizeof(command
->request
)) {
139 SYSERROR("message partially sent to '@%s'", offset
);
143 ret
= receive_answer(sock
, &command
->answer
);
145 if (!stay_connected
|| ret
< 0)
151 extern int lxc_command(const char *name
,
152 struct lxc_command
*command
, int *stopped
,
155 return __lxc_command(name
, command
, stopped
, 0, lxcpath
);
158 extern int lxc_command_connected(const char *name
,
159 struct lxc_command
*command
, int *stopped
,
162 return __lxc_command(name
, command
, stopped
, 1, lxcpath
);
166 pid_t
get_init_pid(const char *name
, const char *lxcpath
)
168 struct lxc_command command
= {
169 .request
= { .type
= LXC_COMMAND_PID
},
172 int ret
, stopped
= 0;
174 ret
= lxc_command(name
, &command
, &stopped
, lxcpath
);
175 if (ret
< 0 && stopped
)
179 ERROR("failed to send command");
183 if (command
.answer
.ret
) {
184 ERROR("failed to retrieve the init pid: %s",
185 strerror(-command
.answer
.ret
));
189 return command
.answer
.pid
;
192 int lxc_get_clone_flags(const char *name
, const char *lxcpath
)
194 struct lxc_command command
= {
195 .request
= { .type
= LXC_COMMAND_CLONE_FLAGS
},
198 int ret
, stopped
= 0;
200 ret
= lxc_command(name
, &command
, &stopped
, lxcpath
);
201 if (ret
< 0 && stopped
)
205 ERROR("failed to send command");
209 return command
.answer
.ret
;
212 extern void lxc_console_remove_fd(int, struct lxc_tty_info
*);
213 extern int lxc_console_callback(int, struct lxc_request
*, struct lxc_handler
*);
214 extern int lxc_stop_callback(int, struct lxc_request
*, struct lxc_handler
*);
215 extern int lxc_state_callback(int, struct lxc_request
*, struct lxc_handler
*);
216 extern int lxc_pid_callback(int, struct lxc_request
*, struct lxc_handler
*);
217 extern int lxc_clone_flags_callback(int, struct lxc_request
*, struct lxc_handler
*);
218 extern int lxc_cgroup_callback(int, struct lxc_request
*, struct lxc_handler
*);
220 static int trigger_command(int fd
, struct lxc_request
*request
,
221 struct lxc_handler
*handler
)
223 typedef int (*callback
)(int, struct lxc_request
*, struct lxc_handler
*);
225 callback cb
[LXC_COMMAND_MAX
] = {
226 [LXC_COMMAND_TTY
] = lxc_console_callback
,
227 [LXC_COMMAND_STOP
] = lxc_stop_callback
,
228 [LXC_COMMAND_STATE
] = lxc_state_callback
,
229 [LXC_COMMAND_PID
] = lxc_pid_callback
,
230 [LXC_COMMAND_CLONE_FLAGS
] = lxc_clone_flags_callback
,
231 [LXC_COMMAND_CGROUP
] = lxc_cgroup_callback
,
234 if (request
->type
< 0 || request
->type
>= LXC_COMMAND_MAX
)
237 return cb
[request
->type
](fd
, request
, handler
);
240 static void command_fd_cleanup(int fd
, struct lxc_handler
*handler
,
241 struct lxc_epoll_descr
*descr
)
243 lxc_console_remove_fd(fd
, &handler
->conf
->tty_info
);
244 lxc_mainloop_del_handler(descr
, fd
);
248 static int command_handler(int fd
, void *data
, struct lxc_epoll_descr
*descr
)
251 struct lxc_request request
;
252 struct lxc_handler
*handler
= data
;
254 ret
= lxc_af_unix_rcv_credential(fd
, &request
, sizeof(request
));
255 if (ret
== -EACCES
) {
256 /* we don't care for the peer, just send and close */
257 struct lxc_answer answer
= { .ret
= ret
};
258 send(fd
, &answer
, sizeof(answer
), 0);
263 SYSERROR("failed to receive data on command socket");
268 DEBUG("peer has disconnected");
272 if (ret
!= sizeof(request
)) {
273 WARN("partial request, ignored");
277 ret
= trigger_command(fd
, &request
, handler
);
279 /* this is not an error, but only a request to close fd */
287 command_fd_cleanup(fd
, handler
, descr
);
291 static int incoming_command_handler(int fd
, void *data
,
292 struct lxc_epoll_descr
*descr
)
294 int opt
= 1, ret
= -1, connection
;
296 connection
= accept(fd
, NULL
, 0);
297 if (connection
< 0) {
298 SYSERROR("failed to accept connection");
302 if (fcntl(connection
, F_SETFD
, FD_CLOEXEC
)) {
303 SYSERROR("failed to set close-on-exec on incoming connection");
307 if (setsockopt(connection
, SOL_SOCKET
,
308 SO_PASSCRED
, &opt
, sizeof(opt
))) {
309 SYSERROR("failed to enable credential on socket");
313 ret
= lxc_mainloop_add_handler(descr
, connection
, command_handler
, data
);
315 ERROR("failed to add handler");
327 extern int lxc_command_init(const char *name
, struct lxc_handler
*handler
,
331 char path
[sizeof(((struct sockaddr_un
*)0)->sun_path
)] = { 0 };
332 char *offset
= &path
[1];
335 len
= sizeof(path
)-1;
336 if (fill_sock_name(offset
, len
, name
, lxcpath
))
339 fd
= lxc_af_unix_open(path
, SOCK_STREAM
, 0);
341 ERROR("failed (%d) to create the command service point %s", errno
, offset
);
342 if (errno
== EADDRINUSE
) {
344 ERROR("# The container appears to be already running!");
350 if (fcntl(fd
, F_SETFD
, FD_CLOEXEC
)) {
351 SYSERROR("failed to set sigfd to close-on-exec");
356 handler
->conf
->maincmd_fd
= fd
;
360 extern int lxc_command_mainloop_add(const char *name
,
361 struct lxc_epoll_descr
*descr
,
362 struct lxc_handler
*handler
)
364 int ret
, fd
= handler
->conf
->maincmd_fd
;
366 ret
= lxc_mainloop_add_handler(descr
, fd
, incoming_command_handler
,
369 ERROR("failed to add handler for command socket");