]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/commands_utils.c
spelling: timeout
[mirror_lxc.git] / src / lxc / commands_utils.c
CommitLineData
92e35018
CB
1/* liblxcapi
2 *
3 * Copyright © 2017 Christian Brauner <christian.brauner@ubuntu.com>.
4 * Copyright © 2017 Canonical Ltd.
5 *
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.
9 *
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.
14 *
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.
18 */
19
d38dd64a
CB
20#ifndef _GNU_SOURCE
21#define _GNU_SOURCE 1
22#endif
bbf5cf35 23#define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
92e35018 24#include <errno.h>
bbf5cf35 25#include <inttypes.h>
92e35018 26#include <stdio.h>
bbf5cf35 27#include <stdlib.h>
92e35018 28#include <string.h>
92e35018
CB
29#include <sys/socket.h>
30#include <sys/un.h>
d38dd64a 31#include <unistd.h>
92e35018 32
c01c2be6 33#include "af_unix.h"
92e35018
CB
34#include "commands.h"
35#include "commands_utils.h"
d38dd64a 36#include "config.h"
e3233f26 37#include "file_utils.h"
d38dd64a 38#include "initutils.h"
92e35018 39#include "log.h"
f3a2945e 40#include "lxclock.h"
92e35018
CB
41#include "monitor.h"
42#include "state.h"
bbf5cf35 43#include "utils.h"
92e35018 44
ac2cecc4 45lxc_log_define(commands_utils, lxc);
92e35018
CB
46
47int lxc_cmd_sock_rcv_state(int state_client_fd, int timeout)
48{
49 int ret;
50 struct lxc_msg msg;
51 struct timeval out;
52
ee8377bd
CB
53 if (timeout >= 0) {
54 memset(&out, 0, sizeof(out));
55 out.tv_sec = timeout;
56 ret = setsockopt(state_client_fd, SOL_SOCKET, SO_RCVTIMEO,
57 (const void *)&out, sizeof(out));
58 if (ret < 0) {
e01516d7 59 SYSERROR("Failed to set %ds timeout on container "
ee8377bd
CB
60 "state socket",
61 timeout);
62 return -1;
63 }
92e35018
CB
64 }
65
66 memset(&msg, 0, sizeof(msg));
67
e3233f26 68 ret = lxc_recv_nointr(state_client_fd, &msg, sizeof(msg), 0);
92e35018 69 if (ret < 0) {
6d1400b5 70 SYSERROR("Failed to receive message");
92e35018
CB
71 return -1;
72 }
73
9dfa4041 74 TRACE("Received state %s from state client %d",
92e35018
CB
75 lxc_state2str(msg.value), state_client_fd);
76
77 return msg.value;
78}
79
80/* Register a new state client and retrieve state from command socket. */
81int lxc_cmd_sock_get_state(const char *name, const char *lxcpath,
82 lxc_state_t states[MAX_STATE], int timeout)
83{
84 int ret;
85 int state_client_fd;
86
87 ret = lxc_cmd_add_state_client(name, lxcpath, states, &state_client_fd);
88 if (ret < 0)
89 return -1;
90
91 if (ret < MAX_STATE)
92 return ret;
93
94 ret = lxc_cmd_sock_rcv_state(state_client_fd, timeout);
95 close(state_client_fd);
96 return ret;
97}
bbf5cf35 98
5b46db1a 99int lxc_make_abstract_socket_name(char *path, size_t pathlen,
100 const char *lxcname,
bbf5cf35
CB
101 const char *lxcpath,
102 const char *hashed_sock_name,
103 const char *suffix)
104{
105 const char *name;
5b46db1a 106 char *offset;
bbf5cf35 107 char *tmppath;
5b46db1a 108 size_t len;
bbf5cf35
CB
109 size_t tmplen;
110 uint64_t hash;
111 int ret;
112
5b46db1a 113 if (!path)
114 return -1;
115
116 offset = &path[1];
117
118 /* -2 here because this is an abstract unix socket so it needs a
119 * leading \0, and we null terminate, so it needs a trailing \0.
120 * Although null termination isn't required by the API, we do it anyway
121 * because we print the sockname out sometimes.
122 */
47903908 123 len = pathlen - 2;
5b46db1a 124
bbf5cf35
CB
125 name = lxcname;
126 if (!name)
127 name = "";
128
129 if (hashed_sock_name != NULL) {
5b46db1a 130 ret = snprintf(offset, len, "lxc/%s/%s", hashed_sock_name, suffix);
bbf5cf35
CB
131 if (ret < 0 || ret >= len) {
132 ERROR("Failed to create abstract socket name");
133 return -1;
134 }
135 return 0;
136 }
137
138 if (!lxcpath) {
139 lxcpath = lxc_global_config_value("lxc.lxcpath");
140 if (!lxcpath) {
141 ERROR("Failed to allocate memory");
142 return -1;
143 }
144 }
145
5b46db1a 146 ret = snprintf(offset, len, "%s/%s/%s", lxcpath, name, suffix);
bbf5cf35
CB
147 if (ret < 0) {
148 ERROR("Failed to create abstract socket name");
149 return -1;
150 }
151 if (ret < len)
152 return 0;
153
154 /* ret >= len; lxcpath or name is too long. hash both */
155 tmplen = strlen(name) + strlen(lxcpath) + 2;
156 tmppath = alloca(tmplen);
157 ret = snprintf(tmppath, tmplen, "%s/%s", lxcpath, name);
158 if (ret < 0 || (size_t)ret >= tmplen) {
159 ERROR("Failed to create abstract socket name");
160 return -1;
161 }
162
163 hash = fnv_64a_buf(tmppath, ret, FNV1A_64_INIT);
5b46db1a 164 ret = snprintf(offset, len, "lxc/%016" PRIx64 "/%s", hash, suffix);
bbf5cf35
CB
165 if (ret < 0 || ret >= len) {
166 ERROR("Failed to create abstract socket name");
167 return -1;
168 }
169
170 return 0;
171}
c01c2be6
CB
172
173int lxc_cmd_connect(const char *name, const char *lxcpath,
9dfa4041 174 const char *hashed_sock_name, const char *suffix)
c01c2be6
CB
175{
176 int ret, client_fd;
b1234129 177 char path[LXC_AUDS_ADDR_LEN] = {0};
c01c2be6 178
5b46db1a 179 ret = lxc_make_abstract_socket_name(path, sizeof(path), name, lxcpath,
9dfa4041 180 hashed_sock_name, suffix);
c01c2be6
CB
181 if (ret < 0)
182 return -1;
183
184 /* Get new client fd. */
185 client_fd = lxc_abstract_unix_connect(path);
2a850b2c 186 if (client_fd < 0)
c01c2be6 187 return -1;
c01c2be6
CB
188
189 return client_fd;
190}
191
192int lxc_add_state_client(int state_client_fd, struct lxc_handler *handler,
193 lxc_state_t states[MAX_STATE])
194{
bc631984 195 int state;
d39b10eb 196 struct lxc_state_client *newclient;
c01c2be6
CB
197 struct lxc_list *tmplist;
198
199 newclient = malloc(sizeof(*newclient));
200 if (!newclient)
201 return -ENOMEM;
202
203 /* copy requested states */
204 memcpy(newclient->states, states, sizeof(newclient->states));
205 newclient->clientfd = state_client_fd;
206
207 tmplist = malloc(sizeof(*tmplist));
208 if (!tmplist) {
209 free(newclient);
210 return -ENOMEM;
211 }
212
bc631984
CB
213 state = handler->state;
214 if (states[state] != 1) {
215 lxc_list_add_elem(tmplist, newclient);
216 lxc_list_add_tail(&handler->conf->state_clients, tmplist);
bc631984 217 } else {
bc631984 218 free(newclient);
44552fb2 219 free(tmplist);
bc631984
CB
220 return state;
221 }
c01c2be6 222
47903908 223 TRACE("Added state client %d to state client list", state_client_fd);
bc631984 224 return MAX_STATE;
c01c2be6 225}