]>
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.
23 #define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
29 #include <sys/socket.h>
35 #include "commands_utils.h"
37 #include "file_utils.h"
38 #include "initutils.h"
45 lxc_log_define(commands_utils
, lxc
);
47 int lxc_cmd_sock_rcv_state(int state_client_fd
, int timeout
)
54 memset(&out
, 0, sizeof(out
));
56 ret
= setsockopt(state_client_fd
, SOL_SOCKET
, SO_RCVTIMEO
,
57 (const void *)&out
, sizeof(out
));
59 SYSERROR("Failed to set %ds timeout on container "
66 memset(&msg
, 0, sizeof(msg
));
68 ret
= lxc_recv_nointr(state_client_fd
, &msg
, sizeof(msg
), 0);
70 SYSERROR("Failed to receive message");
74 TRACE("Received state %s from state client %d",
75 lxc_state2str(msg
.value
), state_client_fd
);
80 /* Register a new state client and retrieve state from command socket. */
81 int lxc_cmd_sock_get_state(const char *name
, const char *lxcpath
,
82 lxc_state_t states
[MAX_STATE
], int timeout
)
87 ret
= lxc_cmd_add_state_client(name
, lxcpath
, states
, &state_client_fd
);
94 ret
= lxc_cmd_sock_rcv_state(state_client_fd
, timeout
);
95 close(state_client_fd
);
99 int lxc_make_abstract_socket_name(char *path
, int len
, const char *lxcname
,
101 const char *hashed_sock_name
,
114 if (hashed_sock_name
!= NULL
) {
116 snprintf(path
, len
, "lxc/%s/%s", hashed_sock_name
, suffix
);
117 if (ret
< 0 || ret
>= len
) {
118 ERROR("Failed to create abstract socket name");
125 lxcpath
= lxc_global_config_value("lxc.lxcpath");
127 ERROR("Failed to allocate memory");
132 ret
= snprintf(path
, len
, "%s/%s/%s", lxcpath
, name
, suffix
);
134 ERROR("Failed to create abstract socket name");
140 /* ret >= len; lxcpath or name is too long. hash both */
141 tmplen
= strlen(name
) + strlen(lxcpath
) + 2;
142 tmppath
= alloca(tmplen
);
143 ret
= snprintf(tmppath
, tmplen
, "%s/%s", lxcpath
, name
);
144 if (ret
< 0 || (size_t)ret
>= tmplen
) {
145 ERROR("Failed to create abstract socket name");
149 hash
= fnv_64a_buf(tmppath
, ret
, FNV1A_64_INIT
);
150 ret
= snprintf(path
, len
, "lxc/%016" PRIx64
"/%s", hash
, suffix
);
151 if (ret
< 0 || ret
>= len
) {
152 ERROR("Failed to create abstract socket name");
159 int lxc_cmd_connect(const char *name
, const char *lxcpath
,
160 const char *hashed_sock_name
, const char *suffix
)
163 char path
[LXC_AUDS_ADDR_LEN
] = {0};
164 char *offset
= &path
[1];
166 /* -2 here because this is an abstract unix socket so it needs a
167 * leading \0, and we null terminate, so it needs a trailing \0.
168 * Although null termination isn't required by the API, we do it anyway
169 * because we print the sockname out sometimes.
171 size_t len
= sizeof(path
) - 2;
172 ret
= lxc_make_abstract_socket_name(offset
, len
, name
, lxcpath
,
173 hashed_sock_name
, suffix
);
177 /* Get new client fd. */
178 client_fd
= lxc_abstract_unix_connect(path
);
185 int lxc_add_state_client(int state_client_fd
, struct lxc_handler
*handler
,
186 lxc_state_t states
[MAX_STATE
])
189 struct lxc_state_client
*newclient
;
190 struct lxc_list
*tmplist
;
192 newclient
= malloc(sizeof(*newclient
));
196 /* copy requested states */
197 memcpy(newclient
->states
, states
, sizeof(newclient
->states
));
198 newclient
->clientfd
= state_client_fd
;
200 tmplist
= malloc(sizeof(*tmplist
));
206 state
= handler
->state
;
207 if (states
[state
] != 1) {
208 lxc_list_add_elem(tmplist
, newclient
);
209 lxc_list_add_tail(&handler
->conf
->state_clients
, tmplist
);
216 TRACE("added state client %d to state client list", state_client_fd
);