]>
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 <dlezcano at fr.ibm.com>
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
28 #include <sys/socket.h>
31 #include <sys/param.h>
39 lxc_log_define(lxc_commands
, lxc
);
41 /*----------------------------------------------------------------------------
42 * functions used by processes requesting command to lxc-start
43 *--------------------------------------------------------------------------*/
44 static int receive_answer(int sock
, struct lxc_answer
*answer
)
48 ret
= lxc_af_unix_recv_fd(sock
, &answer
->fd
, answer
, sizeof(*answer
));
50 ERROR("failed to receive answer for the command");
55 extern int lxc_command(const char *name
, struct lxc_command
*command
)
57 struct sockaddr_un addr
= { 0 };
59 char *offset
= &addr
.sun_path
[1];
61 snprintf(addr
.sun_path
, sizeof(addr
.sun_path
), "@%s", name
);
62 addr
.sun_path
[0] = '\0';
64 sock
= lxc_af_unix_connect(addr
.sun_path
);
66 WARN("failed to connect to '@%s': %s", offset
, strerror(errno
));
70 ret
= lxc_af_unix_send_credential(sock
, &command
->request
,
71 sizeof(command
->request
));
73 SYSERROR("failed to send credentials");
77 if (ret
!= sizeof(command
->request
)) {
78 SYSERROR("message only partially sent to '@%s'", offset
);
82 ret
= receive_answer(sock
, &command
->answer
);
92 /*----------------------------------------------------------------------------
93 * functions used by lxc-start process
94 *--------------------------------------------------------------------------*/
95 extern void lxc_console_remove_fd(int fd
, struct lxc_tty_info
*tty_info
);
96 extern int lxc_console_callback(int fd
, struct lxc_request
*request
,
97 struct lxc_handler
*handler
);
98 extern int lxc_stop_callback(int fd
, struct lxc_request
*request
,
99 struct lxc_handler
*handler
);
101 static int trigger_command(int fd
, struct lxc_request
*request
,
102 struct lxc_handler
*handler
)
104 typedef int (*callback
)(int, struct lxc_request
*,
105 struct lxc_handler
*);
107 callback cb
[LXC_COMMAND_MAX
] = {
108 [LXC_COMMAND_TTY
] = lxc_console_callback
,
109 [LXC_COMMAND_STOP
] = lxc_stop_callback
,
112 if (request
->type
< 0 || request
->type
>= LXC_COMMAND_MAX
)
115 return cb
[request
->type
](fd
, request
, handler
);
118 static void command_fd_cleanup(int fd
, struct lxc_handler
*handler
,
119 struct lxc_epoll_descr
*descr
)
121 lxc_console_remove_fd(fd
, &handler
->tty_info
);
122 lxc_mainloop_del_handler(descr
, fd
);
126 static int command_handler(int fd
, void *data
,
127 struct lxc_epoll_descr
*descr
)
130 struct lxc_request request
;
131 struct lxc_handler
*handler
= data
;
133 ret
= lxc_af_unix_rcv_credential(fd
, &request
, sizeof(request
));
134 if (ret
< 0 && ret
== -EACCES
) {
135 /* we don't care for the peer, just send and close */
136 struct lxc_answer answer
= { .ret
= ret
};
137 send(fd
, &answer
, sizeof(answer
), 0);
139 } else if (ret
< 0) {
140 SYSERROR("failed to receive data on command socket");
145 DEBUG("peer has disconnected");
149 if (ret
!= sizeof(request
)) {
150 WARN("partial request, ignored");
154 ret
= trigger_command(fd
, &request
, handler
);
156 /* this is not an error, but only a request to close fd */
164 command_fd_cleanup(fd
, handler
, descr
);
168 static int incoming_command_handler(int fd
, void *data
,
169 struct lxc_epoll_descr
*descr
)
171 int ret
= 1, connection
;
173 connection
= accept(fd
, NULL
, 0);
174 if (connection
< 0) {
175 SYSERROR("failed to accept connection");
179 if (setsockopt(connection
, SOL_SOCKET
, SO_PASSCRED
, &ret
, sizeof(ret
))) {
180 SYSERROR("failed to enable credential on socket");
184 ret
= lxc_mainloop_add_handler(descr
, connection
, command_handler
, data
);
186 ERROR("failed to add handler");
198 extern int lxc_command_mainloop_add(const char *name
, struct lxc_epoll_descr
*descr
,
199 struct lxc_handler
*handler
)
202 struct sockaddr_un addr
= { 0 };
203 char *offset
= &addr
.sun_path
[1];
205 strcpy(offset
, name
);
206 addr
.sun_path
[0] = '\0';
208 fd
= lxc_af_unix_open(addr
.sun_path
, SOCK_STREAM
, 0);
210 ERROR("failed to create the command service point");
214 ret
= lxc_mainloop_add_handler(descr
, fd
, incoming_command_handler
,
217 ERROR("failed to add handler for command socket");