Clean-up: move global sessiond symbols out of main.o
[lttng-tools.git] / src / bin / lttng-sessiond / session.c
1 /*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2 only,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18 #define _LGPL_SOURCE
19 #include <limits.h>
20 #include <inttypes.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/stat.h>
25 #include <urcu.h>
26 #include <dirent.h>
27 #include <sys/types.h>
28
29 #include <common/common.h>
30 #include <common/sessiond-comm/sessiond-comm.h>
31 #include <lttng/location-internal.h>
32
33 #include "session.h"
34 #include "utils.h"
35 #include "trace-ust.h"
36 #include "timer.h"
37
38 /*
39 * NOTES:
40 *
41 * No ltt_session.lock is taken here because those data structure are widely
42 * spread across the lttng-tools code base so before caling functions below
43 * that can read/write a session, the caller MUST acquire the session lock
44 * using session_lock() and session_unlock().
45 */
46
47 /*
48 * Init tracing session list.
49 *
50 * Please see session.h for more explanation and correct usage of the list.
51 */
52 static struct ltt_session_list ltt_session_list = {
53 .head = CDS_LIST_HEAD_INIT(ltt_session_list.head),
54 .lock = PTHREAD_MUTEX_INITIALIZER,
55 .next_uuid = 0,
56 };
57
58 /* These characters are forbidden in a session name. Used by validate_name. */
59 static const char *forbidden_name_chars = "/";
60
61 /* Global hash table to keep the sessions, indexed by id. */
62 static struct lttng_ht *ltt_sessions_ht_by_id = NULL;
63
64 /*
65 * Validate the session name for forbidden characters.
66 *
67 * Return 0 on success else -1 meaning a forbidden char. has been found.
68 */
69 static int validate_name(const char *name)
70 {
71 int ret;
72 char *tok, *tmp_name;
73
74 assert(name);
75
76 tmp_name = strdup(name);
77 if (!tmp_name) {
78 /* ENOMEM here. */
79 ret = -1;
80 goto error;
81 }
82
83 tok = strpbrk(tmp_name, forbidden_name_chars);
84 if (tok) {
85 DBG("Session name %s contains a forbidden character", name);
86 /* Forbidden character has been found. */
87 ret = -1;
88 goto error;
89 }
90 ret = 0;
91
92 error:
93 free(tmp_name);
94 return ret;
95 }
96
97 /*
98 * Add a ltt_session structure to the global list.
99 *
100 * The caller MUST acquire the session list lock before.
101 * Returns the unique identifier for the session.
102 */
103 static uint64_t add_session_list(struct ltt_session *ls)
104 {
105 assert(ls);
106
107 cds_list_add(&ls->list, &ltt_session_list.head);
108 return ltt_session_list.next_uuid++;
109 }
110
111 /*
112 * Delete a ltt_session structure to the global list.
113 *
114 * The caller MUST acquire the session list lock before.
115 */
116 static void del_session_list(struct ltt_session *ls)
117 {
118 assert(ls);
119
120 cds_list_del(&ls->list);
121 }
122
123 /*
124 * Return a pointer to the session list.
125 */
126 struct ltt_session_list *session_get_list(void)
127 {
128 return &ltt_session_list;
129 }
130
131 /*
132 * Acquire session list lock
133 */
134 void session_lock_list(void)
135 {
136 pthread_mutex_lock(&ltt_session_list.lock);
137 }
138
139 /*
140 * Try to acquire session list lock
141 */
142 int session_trylock_list(void)
143 {
144 return pthread_mutex_trylock(&ltt_session_list.lock);
145 }
146
147 /*
148 * Release session list lock
149 */
150 void session_unlock_list(void)
151 {
152 pthread_mutex_unlock(&ltt_session_list.lock);
153 }
154
155 /*
156 * Get the session's consumer destination type.
157 *
158 * The caller must hold the session lock.
159 */
160 enum consumer_dst_type session_get_consumer_destination_type(
161 const struct ltt_session *session)
162 {
163 /*
164 * The output information is duplicated in both of those session types.
165 * Hence, it doesn't matter from which it is retrieved. However, it is
166 * possible for only one of them to be set.
167 */
168 return session->kernel_session ?
169 session->kernel_session->consumer->type :
170 session->ust_session->consumer->type;
171 }
172
173 /*
174 * Get the session's consumer network hostname.
175 * The caller must ensure that the destination is of type "net".
176 *
177 * The caller must hold the session lock.
178 */
179 const char *session_get_net_consumer_hostname(const struct ltt_session *session)
180 {
181 const char *hostname = NULL;
182 const struct consumer_output *output;
183
184 output = session->kernel_session ?
185 session->kernel_session->consumer :
186 session->ust_session->consumer;
187
188 /*
189 * hostname is assumed to be the same for both control and data
190 * connections.
191 */
192 switch (output->dst.net.control.dtype) {
193 case LTTNG_DST_IPV4:
194 hostname = output->dst.net.control.dst.ipv4;
195 break;
196 case LTTNG_DST_IPV6:
197 hostname = output->dst.net.control.dst.ipv6;
198 break;
199 default:
200 abort();
201 }
202 return hostname;
203 }
204
205 /*
206 * Get the session's consumer network control and data ports.
207 * The caller must ensure that the destination is of type "net".
208 *
209 * The caller must hold the session lock.
210 */
211 void session_get_net_consumer_ports(const struct ltt_session *session,
212 uint16_t *control_port, uint16_t *data_port)
213 {
214 const struct consumer_output *output;
215
216 output = session->kernel_session ?
217 session->kernel_session->consumer :
218 session->ust_session->consumer;
219 *control_port = output->dst.net.control.port;
220 *data_port = output->dst.net.data.port;
221 }
222
223 /*
224 * Get the location of the latest trace archive produced by a rotation.
225 *
226 * The caller must hold the session lock.
227 */
228 struct lttng_trace_archive_location *session_get_trace_archive_location(
229 struct ltt_session *session)
230 {
231 struct lttng_trace_archive_location *location = NULL;
232
233 if (session->rotation_state != LTTNG_ROTATION_STATE_COMPLETED) {
234 goto end;
235 }
236
237 switch (session_get_consumer_destination_type(session)) {
238 case CONSUMER_DST_LOCAL:
239 location = lttng_trace_archive_location_local_create(
240 session->rotation_chunk.current_rotate_path);
241 break;
242 case CONSUMER_DST_NET:
243 {
244 const char *hostname;
245 uint16_t control_port, data_port;
246
247 hostname = session_get_net_consumer_hostname(session);
248 session_get_net_consumer_ports(session,
249 &control_port,
250 &data_port);
251 location = lttng_trace_archive_location_relay_create(
252 hostname,
253 LTTNG_TRACE_ARCHIVE_LOCATION_RELAY_PROTOCOL_TYPE_TCP,
254 control_port, data_port,
255 session->rotation_chunk.current_rotate_path);
256 break;
257 }
258 default:
259 abort();
260 }
261 end:
262 return location;
263 }
264
265 /*
266 * Allocate the ltt_sessions_ht_by_id HT.
267 *
268 * The session list lock must be held.
269 */
270 int ltt_sessions_ht_alloc(void)
271 {
272 int ret = 0;
273
274 DBG("Allocating ltt_sessions_ht_by_id");
275 ltt_sessions_ht_by_id = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
276 if (!ltt_sessions_ht_by_id) {
277 ret = -1;
278 ERR("Failed to allocate ltt_sessions_ht_by_id");
279 goto end;
280 }
281 end:
282 return ret;
283 }
284
285 /*
286 * Destroy the ltt_sessions_ht_by_id HT.
287 *
288 * The session list lock must be held.
289 */
290 static void ltt_sessions_ht_destroy(void)
291 {
292 if (!ltt_sessions_ht_by_id) {
293 return;
294 }
295 ht_cleanup_push(ltt_sessions_ht_by_id);
296 ltt_sessions_ht_by_id = NULL;
297 }
298
299 /*
300 * Add a ltt_session to the ltt_sessions_ht_by_id.
301 * If unallocated, the ltt_sessions_ht_by_id HT is allocated.
302 * The session list lock must be held.
303 */
304 static void add_session_ht(struct ltt_session *ls)
305 {
306 int ret;
307
308 assert(ls);
309
310 if (!ltt_sessions_ht_by_id) {
311 ret = ltt_sessions_ht_alloc();
312 if (ret) {
313 ERR("Error allocating the sessions HT");
314 goto end;
315 }
316 }
317 lttng_ht_node_init_u64(&ls->node, ls->id);
318 lttng_ht_add_unique_u64(ltt_sessions_ht_by_id, &ls->node);
319
320 end:
321 return;
322 }
323
324 /*
325 * Test if ltt_sessions_ht_by_id is empty.
326 * Return 1 if empty, 0 if not empty.
327 * The session list lock must be held.
328 */
329 static int ltt_sessions_ht_empty(void)
330 {
331 int ret;
332
333 if (!ltt_sessions_ht_by_id) {
334 ret = 1;
335 goto end;
336 }
337
338 ret = lttng_ht_get_count(ltt_sessions_ht_by_id) ? 0 : 1;
339 end:
340 return ret;
341 }
342
343 /*
344 * Remove a ltt_session from the ltt_sessions_ht_by_id.
345 * If empty, the ltt_sessions_ht_by_id HT is freed.
346 * The session list lock must be held.
347 */
348 static void del_session_ht(struct ltt_session *ls)
349 {
350 struct lttng_ht_iter iter;
351 int ret;
352
353 assert(ls);
354 assert(ltt_sessions_ht_by_id);
355
356 iter.iter.node = &ls->node.node;
357 ret = lttng_ht_del(ltt_sessions_ht_by_id, &iter);
358 assert(!ret);
359
360 if (ltt_sessions_ht_empty()) {
361 DBG("Empty ltt_sessions_ht_by_id, destroying it");
362 ltt_sessions_ht_destroy();
363 }
364 }
365
366 /*
367 * Acquire session lock
368 */
369 void session_lock(struct ltt_session *session)
370 {
371 assert(session);
372
373 pthread_mutex_lock(&session->lock);
374 }
375
376 /*
377 * Release session lock
378 */
379 void session_unlock(struct ltt_session *session)
380 {
381 assert(session);
382
383 pthread_mutex_unlock(&session->lock);
384 }
385
386 /*
387 * Return a ltt_session structure ptr that matches name. If no session found,
388 * NULL is returned. This must be called with the session list lock held using
389 * session_lock_list and session_unlock_list.
390 */
391 struct ltt_session *session_find_by_name(const char *name)
392 {
393 struct ltt_session *iter;
394
395 assert(name);
396
397 DBG2("Trying to find session by name %s", name);
398
399 cds_list_for_each_entry(iter, &ltt_session_list.head, list) {
400 if (strncmp(iter->name, name, NAME_MAX) == 0) {
401 goto found;
402 }
403 }
404
405 iter = NULL;
406
407 found:
408 return iter;
409 }
410
411 /*
412 * Return an ltt_session that matches the id. If no session is found,
413 * NULL is returned. This must be called with rcu_read_lock and
414 * session list lock held (to guarantee the lifetime of the session).
415 */
416 struct ltt_session *session_find_by_id(uint64_t id)
417 {
418 struct lttng_ht_node_u64 *node;
419 struct lttng_ht_iter iter;
420 struct ltt_session *ls;
421
422 if (!ltt_sessions_ht_by_id) {
423 goto end;
424 }
425
426 lttng_ht_lookup(ltt_sessions_ht_by_id, &id, &iter);
427 node = lttng_ht_iter_get_node_u64(&iter);
428 if (node == NULL) {
429 goto end;
430 }
431 ls = caa_container_of(node, struct ltt_session, node);
432
433 DBG3("Session %" PRIu64 " found by id.", id);
434 return ls;
435
436 end:
437 DBG3("Session %" PRIu64 " NOT found by id", id);
438 return NULL;
439 }
440
441 /*
442 * Delete session from the session list and free the memory.
443 *
444 * Return -1 if no session is found. On success, return 1;
445 * Should *NOT* be called with RCU read-side lock held.
446 */
447 int session_destroy(struct ltt_session *session)
448 {
449 /* Safety check */
450 assert(session);
451
452 DBG("Destroying session %s (id %" PRIu64 ")", session->name, session->id);
453 del_session_list(session);
454 pthread_mutex_destroy(&session->lock);
455 del_session_ht(session);
456
457 consumer_output_put(session->consumer);
458 snapshot_destroy(&session->snapshot);
459 free(session);
460
461 return LTTNG_OK;
462 }
463
464 /*
465 * Create a brand new session and add it to the session list.
466 */
467 int session_create(char *name, uid_t uid, gid_t gid)
468 {
469 int ret;
470 struct ltt_session *new_session;
471
472 /* Allocate session data structure */
473 new_session = zmalloc(sizeof(struct ltt_session));
474 if (new_session == NULL) {
475 PERROR("zmalloc");
476 ret = LTTNG_ERR_FATAL;
477 goto error_malloc;
478 }
479
480 /* Define session name */
481 if (name != NULL) {
482 if (snprintf(new_session->name, NAME_MAX, "%s", name) < 0) {
483 ret = LTTNG_ERR_FATAL;
484 goto error_asprintf;
485 }
486 } else {
487 ERR("No session name given");
488 ret = LTTNG_ERR_FATAL;
489 goto error;
490 }
491
492 ret = validate_name(name);
493 if (ret < 0) {
494 ret = LTTNG_ERR_SESSION_INVALID_CHAR;
495 goto error;
496 }
497
498 ret = gethostname(new_session->hostname, sizeof(new_session->hostname));
499 if (ret < 0) {
500 if (errno == ENAMETOOLONG) {
501 new_session->hostname[sizeof(new_session->hostname) - 1] = '\0';
502 } else {
503 ret = LTTNG_ERR_FATAL;
504 goto error;
505 }
506 }
507
508 /* Init kernel session */
509 new_session->kernel_session = NULL;
510 new_session->ust_session = NULL;
511
512 /* Init lock */
513 pthread_mutex_init(&new_session->lock, NULL);
514
515 new_session->uid = uid;
516 new_session->gid = gid;
517
518 ret = snapshot_init(&new_session->snapshot);
519 if (ret < 0) {
520 ret = LTTNG_ERR_NOMEM;
521 goto error;
522 }
523
524 new_session->rotation_pending_local = false;
525 new_session->rotation_pending_relay = false;
526 new_session->rotation_state = LTTNG_ROTATION_STATE_NO_ROTATION;
527
528 new_session->rotation_pending_check_timer_enabled = false;
529 new_session->rotation_schedule_timer_enabled = false;
530
531 /* Add new session to the session list */
532 session_lock_list();
533 new_session->id = add_session_list(new_session);
534 /*
535 * Add the new session to the ltt_sessions_ht_by_id.
536 * No ownership is taken by the hash table; it is merely
537 * a wrapper around the session list used for faster access
538 * by session id.
539 */
540 add_session_ht(new_session);
541 session_unlock_list();
542
543 /*
544 * Consumer is let to NULL since the create_session_uri command will set it
545 * up and, if valid, assign it to the session.
546 */
547 DBG("Tracing session %s created with ID %" PRIu64 " by UID %d GID %d",
548 name, new_session->id, new_session->uid, new_session->gid);
549
550 return LTTNG_OK;
551
552 error:
553 error_asprintf:
554 free(new_session);
555
556 error_malloc:
557 return ret;
558 }
559
560 /*
561 * Check if the UID or GID match the session. Root user has access to all
562 * sessions.
563 */
564 int session_access_ok(struct ltt_session *session, uid_t uid, gid_t gid)
565 {
566 assert(session);
567
568 if (uid != session->uid && gid != session->gid && uid != 0) {
569 return 0;
570 } else {
571 return 1;
572 }
573 }
This page took 0.040916 seconds and 4 git commands to generate.