]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/commands.c
c api: send lxcpath to destroy command
[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:
7 * Daniel Lezcano <dlezcano at fr.ibm.com>
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
CLG
36#include <lxc/log.h>
37#include <lxc/conf.h>
38#include <lxc/start.h> /* for struct lxc_handler */
2a59a681 39#include <lxc/utils.h>
724e753c
MN
40
41#include "commands.h"
42#include "mainloop.h"
43#include "af_unix.h"
adaeaa99 44#include "config.h"
724e753c 45
ded1d23f
DL
46/*
47 * This file provides the different functions to have the client
48 * and the server to communicate
49 *
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).
53 *
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.
57 *
58 */
59
724e753c
MN
60lxc_log_define(lxc_commands, lxc);
61
13f5be62
SH
62static int fill_sock_name(char *path, int len, const char *name,
63 const char *inpath)
64{
67e571de 65 const char *lxcpath = NULL;
2a59a681 66 int ret;
13f5be62
SH
67
68 if (!inpath) {
69 lxcpath = default_lxc_path();
70 if (!lxcpath) {
71 ERROR("Out of memory getting lxcpath");
72 return -1;
73 }
2a59a681 74 }
13f5be62 75 ret = snprintf(path, len, "%s/%s/command", lxcpath ? lxcpath : inpath, name);
13f5be62 76
2a59a681
SH
77 if (ret < 0 || ret >= len) {
78 ERROR("Name too long");
79 return -1;
80 }
81 return 0;
82}
ded1d23f 83
724e753c
MN
84static int receive_answer(int sock, struct lxc_answer *answer)
85{
86 int ret;
87
88 ret = lxc_af_unix_recv_fd(sock, &answer->fd, answer, sizeof(*answer));
89 if (ret < 0)
90 ERROR("failed to receive answer for the command");
91
92 return ret;
93}
94
43eb6f29 95static int __lxc_command(const char *name, struct lxc_command *command,
13f5be62 96 int *stopped, int stay_connected, const char *lxcpath)
724e753c 97{
724e753c 98 int sock, ret = -1;
46968ea3
DL
99 char path[sizeof(((struct sockaddr_un *)0)->sun_path)] = { 0 };
100 char *offset = &path[1];
2a59a681 101 int len;
724e753c 102
9ba8130c 103 len = sizeof(path)-1;
13f5be62 104 if (fill_sock_name(offset, len, name, lxcpath))
9ba8130c 105 return -1;
724e753c 106
46968ea3 107 sock = lxc_af_unix_connect(path);
d97b36f8
DL
108 if (sock < 0 && errno == ECONNREFUSED) {
109 *stopped = 1;
110 return -1;
111 }
112
724e753c 113 if (sock < 0) {
d97b36f8 114 SYSERROR("failed to connect to '@%s'", offset);
724e753c
MN
115 return -1;
116 }
117
118 ret = lxc_af_unix_send_credential(sock, &command->request,
119 sizeof(command->request));
120 if (ret < 0) {
d97b36f8 121 SYSERROR("failed to send request to '@%s'", offset);
1362f2eb 122 goto out;
724e753c
MN
123 }
124
125 if (ret != sizeof(command->request)) {
d97b36f8 126 SYSERROR("message partially sent to '@%s'", offset);
1362f2eb 127 goto out;
724e753c
MN
128 }
129
130 ret = receive_answer(sock, &command->answer);
724e753c 131out:
43eb6f29
DL
132 if (!stay_connected || ret < 0)
133 close(sock);
134
1362f2eb 135 return ret;
724e753c
MN
136}
137
43eb6f29 138extern int lxc_command(const char *name,
13f5be62
SH
139 struct lxc_command *command, int *stopped,
140 const char *lxcpath)
43eb6f29 141{
13f5be62 142 return __lxc_command(name, command, stopped, 0, lxcpath);
43eb6f29
DL
143}
144
145extern int lxc_command_connected(const char *name,
13f5be62
SH
146 struct lxc_command *command, int *stopped,
147 const char *lxcpath)
43eb6f29 148{
13f5be62 149 return __lxc_command(name, command, stopped, 1, lxcpath);
43eb6f29
DL
150}
151
152
13f5be62 153pid_t get_init_pid(const char *name, const char *lxcpath)
26b2d152
MN
154{
155 struct lxc_command command = {
156 .request = { .type = LXC_COMMAND_PID },
157 };
158
159 int ret, stopped = 0;
160
13f5be62 161 ret = lxc_command(name, &command, &stopped, lxcpath);
ebdd307d 162 if (ret < 0 && stopped)
26b2d152 163 return -1;
26b2d152
MN
164
165 if (ret < 0) {
166 ERROR("failed to send command");
167 return -1;
168 }
169
170 if (command.answer.ret) {
171 ERROR("failed to retrieve the init pid: %s",
172 strerror(-command.answer.ret));
173 return -1;
174 }
175
176 return command.answer.pid;
177}
178
13f5be62 179int lxc_get_clone_flags(const char *name, const char *lxcpath)
d5088cf2
CS
180{
181 struct lxc_command command = {
182 .request = { .type = LXC_COMMAND_CLONE_FLAGS },
183 };
184
185 int ret, stopped = 0;
186
13f5be62 187 ret = lxc_command(name, &command, &stopped, lxcpath);
d5088cf2
CS
188 if (ret < 0 && stopped)
189 return -1;
190
191 if (ret < 0) {
192 ERROR("failed to send command");
193 return -1;
194 }
195
196 return command.answer.ret;
197}
198
ded1d23f
DL
199extern void lxc_console_remove_fd(int, struct lxc_tty_info *);
200extern int lxc_console_callback(int, struct lxc_request *, struct lxc_handler *);
201extern int lxc_stop_callback(int, struct lxc_request *, struct lxc_handler *);
202extern int lxc_state_callback(int, struct lxc_request *, struct lxc_handler *);
81c75799 203extern int lxc_pid_callback(int, struct lxc_request *, struct lxc_handler *);
d5088cf2 204extern int lxc_clone_flags_callback(int, struct lxc_request *, struct lxc_handler *);
724e753c
MN
205
206static int trigger_command(int fd, struct lxc_request *request,
ded1d23f 207 struct lxc_handler *handler)
724e753c 208{
ded1d23f 209 typedef int (*callback)(int, struct lxc_request *, struct lxc_handler *);
724e753c
MN
210
211 callback cb[LXC_COMMAND_MAX] = {
d5088cf2
CS
212 [LXC_COMMAND_TTY] = lxc_console_callback,
213 [LXC_COMMAND_STOP] = lxc_stop_callback,
214 [LXC_COMMAND_STATE] = lxc_state_callback,
215 [LXC_COMMAND_PID] = lxc_pid_callback,
216 [LXC_COMMAND_CLONE_FLAGS] = lxc_clone_flags_callback,
724e753c
MN
217 };
218
219 if (request->type < 0 || request->type >= LXC_COMMAND_MAX)
220 return -1;
221
222 return cb[request->type](fd, request, handler);
223}
224
225static void command_fd_cleanup(int fd, struct lxc_handler *handler,
ded1d23f 226 struct lxc_epoll_descr *descr)
724e753c 227{
fae349da 228 lxc_console_remove_fd(fd, &handler->conf->tty_info);
724e753c
MN
229 lxc_mainloop_del_handler(descr, fd);
230 close(fd);
231}
232
ded1d23f 233static int command_handler(int fd, void *data, struct lxc_epoll_descr *descr)
724e753c
MN
234{
235 int ret;
236 struct lxc_request request;
237 struct lxc_handler *handler = data;
238
239 ret = lxc_af_unix_rcv_credential(fd, &request, sizeof(request));
0a3ec350 240 if (ret == -EACCES) {
3cc5de36
MN
241 /* we don't care for the peer, just send and close */
242 struct lxc_answer answer = { .ret = ret };
243 send(fd, &answer, sizeof(answer), 0);
244 goto out_close;
ded1d23f
DL
245 }
246
247 if (ret < 0) {
724e753c
MN
248 SYSERROR("failed to receive data on command socket");
249 goto out_close;
250 }
251
252 if (!ret) {
253 DEBUG("peer has disconnected");
254 goto out_close;
255 }
256
257 if (ret != sizeof(request)) {
258 WARN("partial request, ignored");
259 goto out_close;
260 }
261
262 ret = trigger_command(fd, &request, handler);
263 if (ret) {
264 /* this is not an error, but only a request to close fd */
265 ret = 0;
266 goto out_close;
267 }
268
269out:
270 return ret;
271out_close:
272 command_fd_cleanup(fd, handler, descr);
273 goto out;
274}
275
276static int incoming_command_handler(int fd, void *data,
277 struct lxc_epoll_descr *descr)
278{
ded1d23f 279 int opt = 1, ret = -1, connection;
724e753c
MN
280
281 connection = accept(fd, NULL, 0);
282 if (connection < 0) {
283 SYSERROR("failed to accept connection");
284 return -1;
285 }
286
9ccb2dbc
DL
287 if (fcntl(connection, F_SETFD, FD_CLOEXEC)) {
288 SYSERROR("failed to set close-on-exec on incoming connection");
289 goto out_close;
290 }
291
0a3ec350
DL
292 if (setsockopt(connection, SOL_SOCKET,
293 SO_PASSCRED, &opt, sizeof(opt))) {
724e753c
MN
294 SYSERROR("failed to enable credential on socket");
295 goto out_close;
296 }
297
298 ret = lxc_mainloop_add_handler(descr, connection, command_handler, data);
299 if (ret) {
300 ERROR("failed to add handler");
301 goto out_close;
302 }
303
304out:
305 return ret;
306
307out_close:
308 close(connection);
309 goto out;
310}
311
13f5be62
SH
312extern int lxc_command_init(const char *name, struct lxc_handler *handler,
313 const char *lxcpath)
724e753c 314{
d2e30e99 315 int fd;
46968ea3
DL
316 char path[sizeof(((struct sockaddr_un *)0)->sun_path)] = { 0 };
317 char *offset = &path[1];
2a59a681 318 int len;
724e753c 319
9ba8130c 320 len = sizeof(path)-1;
13f5be62 321 if (fill_sock_name(offset, len, name, lxcpath))
9ba8130c 322 return -1;
724e753c 323
46968ea3 324 fd = lxc_af_unix_open(path, SOCK_STREAM, 0);
724e753c 325 if (fd < 0) {
97d3756c
SH
326 ERROR("failed (%d) to create the command service point %s", errno, offset);
327 if (errno == EADDRINUSE) {
328 ERROR("##");
329 ERROR("# The container appears to be already running!");
330 ERROR("##");
331 }
724e753c
MN
332 return -1;
333 }
334
91480a0f
DL
335 if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
336 SYSERROR("failed to set sigfd to close-on-exec");
337 close(fd);
338 return -1;
339 }
340
d2e30e99
DE
341 handler->conf->maincmd_fd = fd;
342 return 0;
343}
344
345extern int lxc_command_mainloop_add(const char *name,
346 struct lxc_epoll_descr *descr,
347 struct lxc_handler *handler)
348{
349 int ret, fd = handler->conf->maincmd_fd;
350
0a3ec350
DL
351 ret = lxc_mainloop_add_handler(descr, fd, incoming_command_handler,
352 handler);
724e753c
MN
353 if (ret) {
354 ERROR("failed to add handler for command socket");
355 close(fd);
356 }
357
358 return ret;
359}