Fix: liblttng-ctl: unreported truncations when copying strings
[lttng-tools.git] / src / lib / lttng-ctl / lttng-ctl-health.c
CommitLineData
6c71277b
MD
1/*
2 * lttng-ctl-health.c
3 *
4 * Linux Trace Toolkit Health Control Library
5 *
6 * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
7 * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 *
9 * This library is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License, version 2.1 only,
11 * as published by the Free Software Foundation.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this library; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
6c1c0768 23#define _LGPL_SOURCE
6c71277b
MD
24#include <unistd.h>
25#include <sys/types.h>
26#include <stdint.h>
27#include <limits.h>
28#include <errno.h>
73d8fe3e 29#include <string.h>
6c71277b
MD
30#include <lttng/health-internal.h>
31
32#include <bin/lttng-sessiond/health-sessiond.h>
33#include <bin/lttng-consumerd/health-consumerd.h>
34#include <bin/lttng-relayd/health-relayd.h>
35#include <common/defaults.h>
36#include <common/utils.h>
37
38#include "lttng-ctl-helper.h"
39
40enum health_component {
41 HEALTH_COMPONENT_SESSIOND,
42 HEALTH_COMPONENT_CONSUMERD,
43 HEALTH_COMPONENT_RELAYD,
44
45 NR_HEALTH_COMPONENT,
46};
47
48struct lttng_health_thread {
49 struct lttng_health *p;
50 int state;
51};
52
53struct lttng_health {
54 enum health_component component;
55 uint64_t state;
56 unsigned int nr_threads;
57 char health_sock_path[PATH_MAX];
58 /* For consumer health only */
59 enum lttng_health_consumerd consumerd_type;
60 struct lttng_health_thread thread[];
61};
62
63static
64const char *sessiond_thread_name[NR_HEALTH_SESSIOND_TYPES] = {
65 [ HEALTH_SESSIOND_TYPE_CMD ] = "Session daemon command",
66 [ HEALTH_SESSIOND_TYPE_APP_MANAGE ] = "Session daemon application manager",
67 [ HEALTH_SESSIOND_TYPE_APP_REG ] = "Session daemon application registration",
68 [ HEALTH_SESSIOND_TYPE_KERNEL ] = "Session daemon kernel",
69 [ HEALTH_SESSIOND_TYPE_CONSUMER ] = "Session daemon consumer manager",
70 [ HEALTH_SESSIOND_TYPE_HT_CLEANUP ] = "Session daemon hash table cleanup",
71 [ HEALTH_SESSIOND_TYPE_APP_MANAGE_NOTIFY ] = "Session daemon application notification manager",
72 [ HEALTH_SESSIOND_TYPE_APP_REG_DISPATCH ] = "Session daemon application registration dispatcher",
db66e574 73 [ HEALTH_SESSIOND_TYPE_ROTATION ] = "Session daemon rotation manager",
d086f507 74 [ HEALTH_SESSIOND_TYPE_TIMER ] = "Session daemon timer manager",
6c71277b
MD
75};
76
77static
78const char *consumerd_thread_name[NR_HEALTH_CONSUMERD_TYPES] = {
79 [ HEALTH_CONSUMERD_TYPE_CHANNEL ] = "Consumer daemon channel",
80 [ HEALTH_CONSUMERD_TYPE_METADATA ] = "Consumer daemon metadata",
81 [ HEALTH_CONSUMERD_TYPE_DATA ] = "Consumer daemon data",
82 [ HEALTH_CONSUMERD_TYPE_SESSIOND ] = "Consumer daemon session daemon command manager",
83 [ HEALTH_CONSUMERD_TYPE_METADATA_TIMER ] = "Consumer daemon metadata timer",
84};
85
86static
87const char *relayd_thread_name[NR_HEALTH_RELAYD_TYPES] = {
88 [ HEALTH_RELAYD_TYPE_DISPATCHER ] = "Relay daemon dispatcher",
89 [ HEALTH_RELAYD_TYPE_WORKER ] = "Relay daemon worker",
90 [ HEALTH_RELAYD_TYPE_LISTENER ] = "Relay daemon listener",
e7b0d526
MD
91 [ HEALTH_RELAYD_TYPE_LIVE_DISPATCHER ] = "Relay daemon live dispatcher",
92 [ HEALTH_RELAYD_TYPE_LIVE_WORKER ] = "Relay daemon live worker",
93 [ HEALTH_RELAYD_TYPE_LIVE_LISTENER ] = "Relay daemon live listener",
6c71277b
MD
94};
95
96static
97const char **thread_name[NR_HEALTH_COMPONENT] = {
98 [ HEALTH_COMPONENT_SESSIOND ] = sessiond_thread_name,
99 [ HEALTH_COMPONENT_CONSUMERD] = consumerd_thread_name,
100 [ HEALTH_COMPONENT_RELAYD ] = relayd_thread_name,
101};
102
103/*
104 * Set health socket path.
105 *
55fb8091 106 * Returns 0 on success or a negative errno.
6c71277b
MD
107 */
108static
109int set_health_socket_path(struct lttng_health *lh,
110 int tracing_group)
111{
112 uid_t uid;
113 const char *home;
114 int ret;
115 /* Global and home format strings */
116 const char *global_str, *home_str;
117
118 switch (lh->component) {
119 case HEALTH_COMPONENT_SESSIOND:
120 global_str = DEFAULT_GLOBAL_HEALTH_UNIX_SOCK;
121 home_str = DEFAULT_HOME_HEALTH_UNIX_SOCK;
122 break;
123 case HEALTH_COMPONENT_CONSUMERD:
124 switch (lh->consumerd_type) {
125 case LTTNG_HEALTH_CONSUMERD_UST_32:
126 global_str = DEFAULT_GLOBAL_USTCONSUMER32_HEALTH_UNIX_SOCK;
127 home_str = DEFAULT_HOME_USTCONSUMER32_HEALTH_UNIX_SOCK;
128 break;
129 case LTTNG_HEALTH_CONSUMERD_UST_64:
130 global_str = DEFAULT_GLOBAL_USTCONSUMER64_HEALTH_UNIX_SOCK;
131 home_str = DEFAULT_HOME_USTCONSUMER64_HEALTH_UNIX_SOCK;
132 break;
133 case LTTNG_HEALTH_CONSUMERD_KERNEL:
134 global_str = DEFAULT_GLOBAL_KCONSUMER_HEALTH_UNIX_SOCK;
135 home_str = DEFAULT_HOME_KCONSUMER_HEALTH_UNIX_SOCK;
136 break;
137 default:
138 return -EINVAL;
139 }
140 break;
141 case HEALTH_COMPONENT_RELAYD:
142 if (lh->health_sock_path[0] == '\0') {
143 return -EINVAL;
144 } else {
145 return 0;
146 }
147 break; /* Unreached */
148 default:
149 return -EINVAL;
150 }
151
152 uid = getuid();
153
154 if (uid == 0 || tracing_group) {
55fb8091 155 ret = lttng_strncpy(lh->health_sock_path,
6c71277b
MD
156 global_str,
157 sizeof(lh->health_sock_path));
55fb8091 158 return ret == 0 ? 0 : -EINVAL;
6c71277b
MD
159 }
160
161 /*
162 * With GNU C < 2.1, snprintf returns -1 if the target buffer
163 * is too small; With GNU C >= 2.1, snprintf returns the
164 * required size (excluding closing null).
165 */
166 home = utils_get_home_dir();
167 if (home == NULL) {
168 /* Fallback in /tmp */
169 home = "/tmp";
170 }
171
172 ret = snprintf(lh->health_sock_path, sizeof(lh->health_sock_path),
173 home_str, home);
174 if ((ret < 0) || (ret >= sizeof(lh->health_sock_path))) {
175 return -ENOMEM;
176 }
177
178 return 0;
179}
180
181static
182struct lttng_health *lttng_health_create(enum health_component hc,
183 unsigned int nr_threads)
184{
185 struct lttng_health *lh;
186 int i;
187
188 lh = zmalloc(sizeof(*lh) + sizeof(lh->thread[0]) * nr_threads);
189 if (!lh) {
190 return NULL;
191 }
192
193 lh->component = hc;
194 lh->state = UINT64_MAX; /* All bits in error initially */
195 lh->nr_threads = nr_threads;
196 for (i = 0; i < nr_threads; i++) {
197 lh->thread[i].p = lh;
198 }
199 return lh;
200}
201
202struct lttng_health *lttng_health_create_sessiond(void)
203{
204 struct lttng_health *lh;
205
206 lh = lttng_health_create(HEALTH_COMPONENT_SESSIOND,
207 NR_HEALTH_SESSIOND_TYPES);
208 if (!lh) {
209 return NULL;
210 }
211 return lh;
212}
213
214struct lttng_health *
215 lttng_health_create_consumerd(enum lttng_health_consumerd consumerd)
216{
217 struct lttng_health *lh;
218
219 lh = lttng_health_create(HEALTH_COMPONENT_CONSUMERD,
220 NR_HEALTH_CONSUMERD_TYPES);
221 if (!lh) {
222 return NULL;
223 }
224 lh->consumerd_type = consumerd;
225 return lh;
226}
227
228struct lttng_health *lttng_health_create_relayd(const char *path)
229{
55fb8091
JG
230 int ret;
231 struct lttng_health *lh = NULL;
6c71277b
MD
232
233 if (!path) {
55fb8091 234 goto error;
6c71277b
MD
235 }
236
237 lh = lttng_health_create(HEALTH_COMPONENT_RELAYD,
238 NR_HEALTH_RELAYD_TYPES);
239 if (!lh) {
55fb8091 240 goto error;
6c71277b 241 }
55fb8091
JG
242
243 ret = lttng_strncpy(lh->health_sock_path, path ?: "",
244 sizeof(lh->health_sock_path));
245 if (ret) {
246 goto error;
247 }
248
6c71277b 249 return lh;
55fb8091
JG
250
251error:
252 free(lh);
253 return NULL;
6c71277b
MD
254}
255
256void lttng_health_destroy(struct lttng_health *lh)
257{
258 free(lh);
259}
260
261int lttng_health_query(struct lttng_health *health)
262{
263 int sock, ret, i, tracing_group;
264 struct health_comm_msg msg;
265 struct health_comm_reply reply;
266
267 if (!health) {
268 return -EINVAL;
269 }
270
271 tracing_group = lttng_check_tracing_group();
272retry:
273 ret = set_health_socket_path(health, tracing_group);
274 if (ret) {
275 goto error;
276 }
71d01237 277 /* Connect to component */
6c71277b
MD
278 sock = lttcomm_connect_unix_sock(health->health_sock_path);
279 if (sock < 0) {
280 if (tracing_group) {
281 /* For tracing group, fallback to per-user */
282 tracing_group = 0;
283 goto retry;
284 }
285 ret = -1;
286 goto error;
287 }
288
53efb85a 289 memset(&msg, 0, sizeof(msg));
6c71277b
MD
290 msg.cmd = HEALTH_CMD_CHECK;
291
292 ret = lttcomm_send_unix_sock(sock, (void *)&msg, sizeof(msg));
293 if (ret < 0) {
294 ret = -1;
295 goto close_error;
296 }
297
298 ret = lttcomm_recv_unix_sock(sock, (void *)&reply, sizeof(reply));
299 if (ret < 0) {
300 ret = -1;
301 goto close_error;
302 }
303
304 health->state = reply.ret_code;
305 for (i = 0; i < health->nr_threads; i++) {
306 if (health->state & (1ULL << i)) {
307 health->thread[i].state = -1;
308 } else {
309 health->thread[i].state = 0;
310 }
311 }
312
313close_error:
314 {
315 int closeret;
316
317 closeret = close(sock);
318 assert(!closeret);
319 }
320
321error:
322 if (ret >= 0)
323 ret = 0;
324 return ret;
325}
326
327int lttng_health_state(const struct lttng_health *health)
328{
329 if (!health) {
330 return -EINVAL;
331 }
332
333 if (health->state == 0) {
334 return 0;
335 } else {
336 return -1;
337 }
338}
339
340int lttng_health_get_nr_threads(const struct lttng_health *health)
341{
342 if (!health) {
343 return -EINVAL;
344 }
345 return health->nr_threads;
346}
347
348const struct lttng_health_thread *
349 lttng_health_get_thread(const struct lttng_health *health,
350 unsigned int nth_thread)
351{
352 if (!health || nth_thread >= health->nr_threads) {
353 return NULL;
354 }
355 return &health->thread[nth_thread];
356}
357
358int lttng_health_thread_state(const struct lttng_health_thread *thread)
359{
360 if (!thread) {
361 return -EINVAL;
362 }
363 return thread->state;
364}
365
366const char *lttng_health_thread_name(const struct lttng_health_thread *thread)
367{
368 unsigned int nr;
369
370 if (!thread) {
371 return NULL;
372 }
373 nr = thread - &thread->p->thread[0];
374 return thread_name[thread->p->component][nr];
375}
This page took 0.070753 seconds and 4 git commands to generate.