X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-relayd%2Fmain.c;h=5f72c32a906f700ec14009766d056ead3e49b375;hp=431a0d67a056a227c6b58afac9da052a779ac46d;hb=2a10de3b3b5a198a1633ff4167a9610c493994c1;hpb=f8be11834749a7ba0b5f499b11c048d62d98a068 diff --git a/src/bin/lttng-relayd/main.c b/src/bin/lttng-relayd/main.c index 431a0d67a..5f72c32a9 100644 --- a/src/bin/lttng-relayd/main.c +++ b/src/bin/lttng-relayd/main.c @@ -62,6 +62,7 @@ #include #include +#include "version.h" #include "cmd.h" #include "ctf-trace.h" #include "index.h" @@ -95,8 +96,8 @@ enum relay_connection_status { }; /* command line options */ -char *opt_output_path; -static int opt_daemon, opt_background; +char *opt_output_path, *opt_working_directory; +static int opt_daemon, opt_background, opt_print_version; /* * We need to wait for listener and live listener threads, as well as @@ -183,11 +184,29 @@ static struct option long_options[] = { { "verbose", 0, 0, 'v', }, { "config", 1, 0, 'f' }, { "version", 0, 0, 'V' }, + { "working-directory", 1, 0, 'w', }, { NULL, 0, 0, 0, }, }; static const char *config_ignore_options[] = { "help", "config", "version" }; +static void print_version(void) { + fprintf(stdout, "%s\n", VERSION); +} + +static void relayd_config_log(void) +{ + DBG("LTTng-relayd " VERSION " - " VERSION_NAME "%s%s", + GIT_VERSION[0] == '\0' ? "" : " - " GIT_VERSION, + EXTRA_VERSION_NAME[0] == '\0' ? "" : " - " EXTRA_VERSION_NAME); + if (EXTRA_VERSION_DESCRIPTION[0] != '\0') { + DBG("LTTng-relayd extra version description:\n\t" EXTRA_VERSION_DESCRIPTION "\n"); + } + if (EXTRA_VERSION_PATCHES[0] != '\0') { + DBG("LTTng-relayd extra patches:\n\t" EXTRA_VERSION_PATCHES "\n"); + } +} + /* * Take an option from the getopt output and set it in the right variable to be * used later. @@ -278,8 +297,8 @@ static int set_option(int opt, const char *arg, const char *optname) } exit(EXIT_FAILURE); case 'V': - fprintf(stdout, "%s\n", VERSION); - exit(EXIT_SUCCESS); + opt_print_version = 1; + break; case 'o': if (lttng_is_setuid_setgid()) { WARN("Getting '%s' argument from setuid/setgid binary refused for security reasons.", @@ -293,6 +312,20 @@ static int set_option(int opt, const char *arg, const char *optname) } } break; + case 'w': + if (lttng_is_setuid_setgid()) { + WARN("Getting '%s' argument from setuid/setgid binary refused for security reasons.", + "-w, --working-directory"); + } else { + ret = asprintf(&opt_working_directory, "%s", arg); + if (ret < 0) { + ret = -errno; + PERROR("asprintf opt_working_directory"); + goto end; + } + } + break; + case 'v': /* Verbose level can increase using multiple -v */ if (arg) { @@ -373,6 +406,23 @@ end: return ret; } +static int parse_env_options(void) +{ + int ret = 0; + char *value = NULL; + + value = lttng_secure_getenv(DEFAULT_LTTNG_RELAYD_WORKING_DIRECTORY_ENV); + if (value) { + opt_working_directory = strdup(value); + if (!opt_working_directory) { + ERR("Failed to allocate working directory string (\"%s\")", + value); + ret = -1; + } + } + return ret; +} + static int set_options(int argc, char **argv) { int c, ret = 0, option_index = 0, retval = 0; @@ -523,8 +573,8 @@ static void relayd_cleanup(void) if (sessions_ht) lttng_ht_destroy(sessions_ht); - /* free the dynamically allocated opt_output_path */ free(opt_output_path); + free(opt_working_directory); /* Close thread quit pipes */ utils_close_pipe(thread_quit_pipe); @@ -1157,21 +1207,24 @@ send_reply: } } else { const uint32_t output_path_length = - strlen(session->output_path) + 1; + session ? strlen(session->output_path) + 1 : 0; reply.output_path_length = htobe32(output_path_length); - ret = lttng_dynamic_buffer_append(&reply_payload, &reply, - sizeof(reply)); + ret = lttng_dynamic_buffer_append( + &reply_payload, &reply, sizeof(reply)); if (ret) { ERR("Failed to append \"create session\" command reply header to payload buffer"); goto end; } - ret = lttng_dynamic_buffer_append(&reply_payload, - session->output_path, output_path_length); - if (ret) { - ERR("Failed to append \"create session\" command reply path to payload buffer"); - goto end; + if (output_path_length) { + ret = lttng_dynamic_buffer_append(&reply_payload, + session->output_path, + output_path_length); + if (ret) { + ERR("Failed to append \"create session\" command reply path to payload buffer"); + goto end; + } } } @@ -2279,6 +2332,7 @@ static int relay_rotate_session_streams( } reply_code = LTTNG_OK; + ret = 0; end: if (stream) { stream_put(stream); @@ -2292,8 +2346,6 @@ end: send_ret); ret = -1; } - - ret = 0; end_no_reply: lttng_trace_chunk_put(next_trace_chunk); return ret; @@ -2386,13 +2438,6 @@ static int relay_create_trace_chunk(const struct lttcomm_relayd_hdr *recv_hdr, } } - ret = session_init_output_directory_handle( - conn->session, &session_output); - if (ret) { - reply_code = LTTNG_ERR_CREATE_DIR_FAIL; - goto end; - } - chunk_status = lttng_trace_chunk_set_credentials_current_user(chunk); if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) { reply_code = LTTNG_ERR_UNK; @@ -2400,7 +2445,14 @@ static int relay_create_trace_chunk(const struct lttcomm_relayd_hdr *recv_hdr, goto end; } + ret = session_init_output_directory_handle( + conn->session, &session_output); + if (ret) { + reply_code = LTTNG_ERR_CREATE_DIR_FAIL; + goto end; + } chunk_status = lttng_trace_chunk_set_as_owner(chunk, &session_output); + lttng_directory_handle_fini(&session_output); if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) { reply_code = LTTNG_ERR_UNK; ret = -1; @@ -2456,7 +2508,6 @@ end: end_no_reply: lttng_trace_chunk_put(chunk); lttng_trace_chunk_put(published_chunk); - lttng_directory_handle_fini(&session_output); return ret; } @@ -2467,7 +2518,7 @@ static int relay_close_trace_chunk(const struct lttcomm_relayd_hdr *recv_hdr, struct relay_connection *conn, const struct lttng_buffer_view *payload) { - int ret = 0; + int ret = 0, buf_ret; ssize_t send_ret; struct relay_session *session = conn->session; struct lttcomm_relayd_close_trace_chunk *msg; @@ -2628,17 +2679,17 @@ end_unlock_session: end: reply.generic.ret_code = htobe32((uint32_t) reply_code); reply.path_length = htobe32((uint32_t) path_length); - ret = lttng_dynamic_buffer_append( + buf_ret = lttng_dynamic_buffer_append( &reply_payload, &reply, sizeof(reply)); - if (ret) { + if (buf_ret) { ERR("Failed to append \"close trace chunk\" command reply header to payload buffer"); goto end_no_reply; } if (reply_code == LTTNG_OK) { - ret = lttng_dynamic_buffer_append(&reply_payload, + buf_ret = lttng_dynamic_buffer_append(&reply_payload, closed_trace_chunk_path, path_length); - if (ret) { + if (buf_ret) { ERR("Failed to append \"close trace chunk\" command reply path to payload buffer"); goto end_no_reply; } @@ -2673,8 +2724,8 @@ static int relay_trace_chunk_exists(const struct lttcomm_relayd_hdr *recv_hdr, struct lttcomm_relayd_trace_chunk_exists *msg; struct lttcomm_relayd_trace_chunk_exists_reply reply = {}; struct lttng_buffer_view header_view; - struct lttng_trace_chunk *chunk = NULL; uint64_t chunk_id; + bool chunk_exists; if (!session || !conn->version_check_done) { ERR("Trying to close a trace chunk before version check"); @@ -2699,25 +2750,29 @@ static int relay_trace_chunk_exists(const struct lttcomm_relayd_hdr *recv_hdr, msg = (typeof(msg)) header_view.data; chunk_id = be64toh(msg->chunk_id); - chunk = sessiond_trace_chunk_registry_get_chunk( + ret = sessiond_trace_chunk_registry_chunk_exists( sessiond_trace_chunk_registry, conn->session->sessiond_uuid, conn->session->id, - chunk_id); - - reply = (typeof(reply)) { - .generic.ret_code = htobe32((uint32_t) LTTNG_OK), - .trace_chunk_exists = !!chunk, + chunk_id, &chunk_exists); + /* + * If ret is not 0, send the reply and report the error to the caller. + * It is a protocol (or internal) error and the session/connection + * should be torn down. + */ + reply = (typeof(reply)){ + .generic.ret_code = htobe32((uint32_t) + (ret == 0 ? LTTNG_OK : LTTNG_ERR_INVALID_PROTOCOL)), + .trace_chunk_exists = ret == 0 ? chunk_exists : 0, }; - send_ret = conn->sock->ops->sendmsg(conn->sock, - &reply, sizeof(reply), 0); + send_ret = conn->sock->ops->sendmsg( + conn->sock, &reply, sizeof(reply), 0); if (send_ret < (ssize_t) sizeof(reply)) { ERR("Failed to send \"create trace chunk\" command reply (ret = %zd)", send_ret); ret = -1; } end_no_reply: - lttng_trace_chunk_put(chunk); return ret; } @@ -3398,8 +3453,13 @@ restart: if (ret < 0) { goto error; } - lttng_poll_add(&events, conn->sock->fd, + ret = lttng_poll_add(&events, + conn->sock->fd, LPOLLIN | LPOLLRDHUP); + if (ret) { + ERR("Failed to add new connection file descriptor to poll set"); + goto error; + } connection_ht_add(relay_connections_ht, conn); DBG("Connection socket %d added", conn->sock->fd); } else if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { @@ -3643,7 +3703,17 @@ int main(int argc, char **argv) int ret = 0, retval = 0; void *status; - /* Parse arguments */ + /* Parse environment variables */ + ret = parse_env_options(); + if (ret) { + retval = -1; + goto exit_options; + } + + /* + * Parse arguments. + * Command line arguments overwrite environment. + */ progname = argv[0]; if (set_options(argc, argv)) { retval = -1; @@ -3655,6 +3725,14 @@ int main(int argc, char **argv) goto exit_options; } + relayd_config_log(); + + if (opt_print_version) { + print_version(); + retval = 0; + goto exit_options; + } + /* Try to create directory if -o, --output is specified. */ if (opt_output_path) { if (*opt_output_path != '/') { @@ -3693,6 +3771,14 @@ int main(int argc, char **argv) } } + if (opt_working_directory) { + ret = utils_change_working_directory(opt_working_directory); + if (ret) { + /* All errors are already logged. */ + goto exit_options; + } + } + sessiond_trace_chunk_registry = sessiond_trace_chunk_registry_create(); if (!sessiond_trace_chunk_registry) { ERR("Failed to initialize session daemon trace chunk registry");