]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/commands_utils.c
3 * Copyright © 2017 Christian Brauner <christian.brauner@ubuntu.com>.
4 * Copyright © 2017 Canonical Ltd.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2, as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
28 #include <sys/socket.h>
33 #include "commands_utils.h"
34 #include "initutils.h"
41 lxc_log_define(lxc_commands_utils
, lxc
);
43 int lxc_cmd_sock_rcv_state(int state_client_fd
, int timeout
)
50 memset(&out
, 0, sizeof(out
));
52 ret
= setsockopt(state_client_fd
, SOL_SOCKET
, SO_RCVTIMEO
,
53 (const void *)&out
, sizeof(out
));
55 SYSERROR("Failed to set %ds timeout on containter "
62 memset(&msg
, 0, sizeof(msg
));
65 ret
= recv(state_client_fd
, &msg
, sizeof(msg
), 0);
68 TRACE("Caught EINTR; retrying");
72 ERROR("Failed to receive message: %s", strerror(errno
));
79 TRACE("Received state %s from state client %d",
80 lxc_state2str(msg
.value
), state_client_fd
);
85 /* Register a new state client and retrieve state from command socket. */
86 int lxc_cmd_sock_get_state(const char *name
, const char *lxcpath
,
87 lxc_state_t states
[MAX_STATE
], int timeout
)
92 ret
= lxc_cmd_add_state_client(name
, lxcpath
, states
, &state_client_fd
);
99 ret
= lxc_cmd_sock_rcv_state(state_client_fd
, timeout
);
100 close(state_client_fd
);
104 int lxc_make_abstract_socket_name(char *path
, int len
, const char *lxcname
,
106 const char *hashed_sock_name
,
119 if (hashed_sock_name
!= NULL
) {
121 snprintf(path
, len
, "lxc/%s/%s", hashed_sock_name
, suffix
);
122 if (ret
< 0 || ret
>= len
) {
123 ERROR("Failed to create abstract socket name");
130 lxcpath
= lxc_global_config_value("lxc.lxcpath");
132 ERROR("Failed to allocate memory");
137 ret
= snprintf(path
, len
, "%s/%s/%s", lxcpath
, name
, suffix
);
139 ERROR("Failed to create abstract socket name");
145 /* ret >= len; lxcpath or name is too long. hash both */
146 tmplen
= strlen(name
) + strlen(lxcpath
) + 2;
147 tmppath
= alloca(tmplen
);
148 ret
= snprintf(tmppath
, tmplen
, "%s/%s", lxcpath
, name
);
149 if (ret
< 0 || (size_t)ret
>= tmplen
) {
150 ERROR("Failed to create abstract socket name");
154 hash
= fnv_64a_buf(tmppath
, ret
, FNV1A_64_INIT
);
155 ret
= snprintf(path
, len
, "lxc/%016" PRIx64
"/%s", hash
, suffix
);
156 if (ret
< 0 || ret
>= len
) {
157 ERROR("Failed to create abstract socket name");
164 int lxc_cmd_connect(const char *name
, const char *lxcpath
,
165 const char *hashed_sock_name
, const char *suffix
)
168 char path
[sizeof(((struct sockaddr_un
*)0)->sun_path
)] = {0};
169 char *offset
= &path
[1];
171 /* -2 here because this is an abstract unix socket so it needs a
172 * leading \0, and we null terminate, so it needs a trailing \0.
173 * Although null termination isn't required by the API, we do it anyway
174 * because we print the sockname out sometimes.
176 size_t len
= sizeof(path
) - 2;
177 ret
= lxc_make_abstract_socket_name(offset
, len
, name
, lxcpath
,
178 hashed_sock_name
, suffix
);
182 /* Get new client fd. */
183 client_fd
= lxc_abstract_unix_connect(path
);
185 if (errno
== ECONNREFUSED
)
186 return -ECONNREFUSED
;
193 int lxc_add_state_client(int state_client_fd
, struct lxc_handler
*handler
,
194 lxc_state_t states
[MAX_STATE
])
197 struct lxc_state_client
*newclient
;
198 struct lxc_list
*tmplist
;
200 newclient
= malloc(sizeof(*newclient
));
204 /* copy requested states */
205 memcpy(newclient
->states
, states
, sizeof(newclient
->states
));
206 newclient
->clientfd
= state_client_fd
;
208 tmplist
= malloc(sizeof(*tmplist
));
215 state
= handler
->state
;
216 if (states
[state
] != 1) {
217 lxc_list_add_elem(tmplist
, newclient
);
218 lxc_list_add_tail(&handler
->conf
->state_clients
, tmplist
);
227 TRACE("added state client %d to state client list", state_client_fd
);