]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/commands_utils.c
commands_utils.c: fix wrong licensing
[mirror_lxc.git] / src / lxc / commands_utils.c
CommitLineData
92e35018
CB
1/* liblxcapi
2 *
ddaa5226
CB
3 * Copyright © 2019 Christian Brauner <christian.brauner@ubuntu.com>.
4 * Copyright © 2019 Canonical Ltd.
92e35018 5 *
ddaa5226
CB
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10
11 * This library is distributed in the hope that it will be useful,
92e35018 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ddaa5226
CB
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this library; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
92e35018
CB
19 */
20
d38dd64a
CB
21#ifndef _GNU_SOURCE
22#define _GNU_SOURCE 1
23#endif
bbf5cf35 24#define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
92e35018 25#include <errno.h>
bbf5cf35 26#include <inttypes.h>
92e35018 27#include <stdio.h>
bbf5cf35 28#include <stdlib.h>
92e35018 29#include <string.h>
92e35018
CB
30#include <sys/socket.h>
31#include <sys/un.h>
d38dd64a 32#include <unistd.h>
92e35018 33
c01c2be6 34#include "af_unix.h"
92e35018
CB
35#include "commands.h"
36#include "commands_utils.h"
d38dd64a 37#include "config.h"
e3233f26 38#include "file_utils.h"
d38dd64a 39#include "initutils.h"
92e35018 40#include "log.h"
f3a2945e 41#include "lxclock.h"
fdcdb654 42#include "memory_utils.h"
92e35018
CB
43#include "monitor.h"
44#include "state.h"
bbf5cf35 45#include "utils.h"
92e35018 46
ac2cecc4 47lxc_log_define(commands_utils, lxc);
92e35018
CB
48
49int lxc_cmd_sock_rcv_state(int state_client_fd, int timeout)
50{
51 int ret;
52 struct lxc_msg msg;
53 struct timeval out;
54
ee8377bd
CB
55 if (timeout >= 0) {
56 memset(&out, 0, sizeof(out));
57 out.tv_sec = timeout;
58 ret = setsockopt(state_client_fd, SOL_SOCKET, SO_RCVTIMEO,
59 (const void *)&out, sizeof(out));
60 if (ret < 0) {
e01516d7 61 SYSERROR("Failed to set %ds timeout on container "
ee8377bd
CB
62 "state socket",
63 timeout);
64 return -1;
65 }
92e35018
CB
66 }
67
68 memset(&msg, 0, sizeof(msg));
69
e3233f26 70 ret = lxc_recv_nointr(state_client_fd, &msg, sizeof(msg), 0);
92e35018 71 if (ret < 0) {
6d1400b5 72 SYSERROR("Failed to receive message");
92e35018
CB
73 return -1;
74 }
75
9dfa4041 76 TRACE("Received state %s from state client %d",
92e35018
CB
77 lxc_state2str(msg.value), state_client_fd);
78
79 return msg.value;
80}
81
82/* Register a new state client and retrieve state from command socket. */
83int lxc_cmd_sock_get_state(const char *name, const char *lxcpath,
84 lxc_state_t states[MAX_STATE], int timeout)
85{
b02dc0d9 86 __do_close_prot_errno int state_client_fd = -EBADF;
92e35018 87 int ret;
92e35018
CB
88
89 ret = lxc_cmd_add_state_client(name, lxcpath, states, &state_client_fd);
90 if (ret < 0)
91 return -1;
92
93 if (ret < MAX_STATE)
94 return ret;
95
b02dc0d9 96 return lxc_cmd_sock_rcv_state(state_client_fd, timeout);
92e35018 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{
fdcdb654 105 __do_free char *tmppath = NULL;
bbf5cf35 106 const char *name;
5b46db1a 107 char *offset;
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;
fdcdb654 156 tmppath = must_realloc(NULL, tmplen);
bbf5cf35
CB
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{
7fda348e
CB
195 __do_free struct lxc_state_client *newclient = NULL;
196 __do_free struct lxc_list *tmplist = NULL;
bc631984 197 int state;
c01c2be6
CB
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));
7fda348e 208 if (!tmplist)
c01c2be6 209 return -ENOMEM;
c01c2be6 210
bc631984
CB
211 state = handler->state;
212 if (states[state] != 1) {
213 lxc_list_add_elem(tmplist, newclient);
214 lxc_list_add_tail(&handler->conf->state_clients, tmplist);
bc631984 215 } else {
bc631984
CB
216 return state;
217 }
c01c2be6 218
47903908 219 TRACE("Added state client %d to state client list", state_client_fd);
7fda348e
CB
220 move_ptr(newclient);
221 move_ptr(tmplist);
bc631984 222 return MAX_STATE;
c01c2be6 223}