X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=liblttngctl%2Flttngctl.c;h=9c3735f38f9a2896b2f4e0d611adef2a682e76ca;hp=14055ed48451b652b06db40e72e7b1de013e3bff;hb=6299f964b03eb3a3074dbe872907794d20da8af0;hpb=cd80958d00fddabced5fbd60641978516a01e29e diff --git a/liblttngctl/lttngctl.c b/liblttngctl/lttngctl.c index 14055ed48..9c3735f38 100644 --- a/liblttngctl/lttngctl.c +++ b/liblttngctl/lttngctl.c @@ -21,18 +21,17 @@ */ #define _GNU_SOURCE -#include #include +#include #include #include #include #include -#include - #include -#include "lttngerr.h" -#include "lttng-share.h" +#include +#include +#include /* Socket to session daemon for communication */ static int sessiond_socket; @@ -47,7 +46,7 @@ static int connected; */ static void copy_string(char *dst, const char *src, size_t len) { - if (src) { + if (src && dst) { strncpy(dst, src, len); /* Enforce the NULL terminated byte */ dst[len - 1] = '\0'; @@ -125,7 +124,7 @@ end: /* * Check if the specified group name exist. * - * If yes return 0, else return -1. + * If yes return 1, else return -1. */ static int check_tracing_group(const char *grp_name) { @@ -153,6 +152,10 @@ static int check_tracing_group(const char *grp_name) /* Alloc group list of the right size */ grp_list = malloc(grp_list_size * sizeof(gid_t)); + if (!grp_list) { + ret = -1; + goto end; + } grp_id = getgroups(grp_list_size, grp_list); if (grp_id < -1) { perror("getgroups"); @@ -161,7 +164,7 @@ static int check_tracing_group(const char *grp_name) for (i = 0; i < grp_list_size; i++) { if (grp_list[i] == grp_tracing->gr_gid) { - ret = 0; + ret = 1; break; } } @@ -174,25 +177,79 @@ end: } /* - * Set sessiond socket path by putting it in the global sessiond_sock_path - * variable. + * Try connect to session daemon with sock_path. + * + * Return 0 on success, else -1 + */ +static int try_connect_sessiond(const char *sock_path) +{ + int ret; + + /* If socket exist, we check if the daemon listens for connect. */ + ret = access(sock_path, F_OK); + if (ret < 0) { + /* Not alive */ + return -1; + } + + ret = lttcomm_connect_unix_sock(sock_path); + if (ret < 0) { + /* Not alive */ + return -1; + } + + ret = lttcomm_close_unix_sock(ret); + if (ret < 0) { + perror("lttcomm_close_unix_sock"); + } + + return 0; +} + +/* + * Set sessiond socket path by putting it in the global sessiond_sock_path + * variable. */ static int set_session_daemon_path(void) { int ret; + int in_tgroup = 0; /* In tracing group */ + uid_t uid; + + uid = getuid(); - /* Are we in the tracing group ? */ - ret = check_tracing_group(tracing_group); - if (ret < 0 && getuid() != 0) { + if (uid != 0) { + /* Are we in the tracing group ? */ + in_tgroup = check_tracing_group(tracing_group); + } + + if (uid == 0) { + /* Root */ + copy_string(sessiond_sock_path, + DEFAULT_GLOBAL_CLIENT_UNIX_SOCK, + sizeof(sessiond_sock_path)); + } else if (in_tgroup) { + /* Tracing group */ + copy_string(sessiond_sock_path, + DEFAULT_GLOBAL_CLIENT_UNIX_SOCK, + sizeof(sessiond_sock_path)); + + ret = try_connect_sessiond(sessiond_sock_path); + if (ret < 0) { + /* Global session daemon not available */ + if (snprintf(sessiond_sock_path, sizeof(sessiond_sock_path), + DEFAULT_HOME_CLIENT_UNIX_SOCK, + getenv("HOME")) < 0) { + return -ENOMEM; + } + } + } else { + /* Not in tracing group and not root, default */ if (snprintf(sessiond_sock_path, PATH_MAX, DEFAULT_HOME_CLIENT_UNIX_SOCK, getenv("HOME")) < 0) { return -ENOMEM; } - } else { - copy_string(sessiond_sock_path, - DEFAULT_GLOBAL_CLIENT_UNIX_SOCK, - PATH_MAX); } return 0; @@ -277,6 +334,10 @@ static int ask_sessiond(struct lttcomm_session_msg *lsm, void **buf) size = llm.data_size; if (size == 0) { + /* If client free with size 0 */ + if (buf != NULL) { + *buf = NULL; + } ret = 0; goto end; } @@ -290,6 +351,16 @@ static int ask_sessiond(struct lttcomm_session_msg *lsm, void **buf) goto end; } + /* + * Extra protection not to dereference a NULL pointer. If buf is NULL at + * this point, an error is returned and data is freed. + */ + if (buf == NULL) { + ret = -1; + free(data); + goto end; + } + *buf = data; ret = size; @@ -333,6 +404,24 @@ void lttng_destroy_handle(struct lttng_handle *handle) } } +/* + * Register an outside consumer. + */ +int lttng_register_consumer(struct lttng_handle *handle, + const char *socket_path) +{ + struct lttcomm_session_msg lsm; + + lsm.cmd_type = LTTNG_REGISTER_CONSUMER; + copy_string(lsm.session.name, handle->session_name, + sizeof(lsm.session.name)); + copy_lttng_domain(&lsm.domain, &handle->domain); + + copy_string(lsm.u.reg.path, socket_path, sizeof(lsm.u.reg.path)); + + return ask_sessiond(&lsm, NULL); +} + /* * Start tracing for all trace of the session. */ @@ -340,7 +429,7 @@ int lttng_start_tracing(struct lttng_handle *handle) { struct lttcomm_session_msg lsm; - if (!handle) { + if (handle == NULL) { return -1; } @@ -374,7 +463,8 @@ int lttng_add_context(struct lttng_handle *handle, { struct lttcomm_session_msg lsm; - if (!handle) { + /* Safety check. Both are mandatory */ + if (handle == NULL || ctx == NULL) { return -1; } @@ -389,9 +479,7 @@ int lttng_add_context(struct lttng_handle *handle, copy_lttng_domain(&lsm.domain, &handle->domain); - if (ctx) { - memcpy(&lsm.u.context.ctx, ctx, sizeof(struct lttng_event_context)); - } + memcpy(&lsm.u.context.ctx, ctx, sizeof(struct lttng_event_context)); copy_string(lsm.session.name, handle->session_name, sizeof(lsm.session.name)); @@ -407,10 +495,11 @@ int lttng_enable_event(struct lttng_handle *handle, { struct lttcomm_session_msg lsm; - if (!handle) { + if (handle == NULL || ev == NULL) { return -1; } + /* If no channel name, we put the default name */ if (channel_name == NULL) { copy_string(lsm.u.enable.channel_name, DEFAULT_CHANNEL_NAME, sizeof(lsm.u.enable.channel_name)); @@ -421,12 +510,12 @@ int lttng_enable_event(struct lttng_handle *handle, copy_lttng_domain(&lsm.domain, &handle->domain); - if (ev) { + if (ev->name[0] != '\0') { lsm.cmd_type = LTTNG_ENABLE_EVENT; - memcpy(&lsm.u.enable.event, ev, sizeof(lsm.u.enable.event)); } else { lsm.cmd_type = LTTNG_ENABLE_ALL_EVENT; } + memcpy(&lsm.u.enable.event, ev, sizeof(lsm.u.enable.event)); copy_string(lsm.session.name, handle->session_name, sizeof(lsm.session.name)); @@ -442,7 +531,7 @@ int lttng_disable_event(struct lttng_handle *handle, const char *name, { struct lttcomm_session_msg lsm; - if (!handle) { + if (handle == NULL) { return -1; } @@ -456,7 +545,7 @@ int lttng_disable_event(struct lttng_handle *handle, const char *name, copy_lttng_domain(&lsm.domain, &handle->domain); - if (name == NULL) { + if (name != NULL) { copy_string(lsm.u.disable.name, name, sizeof(lsm.u.disable.name)); lsm.cmd_type = LTTNG_DISABLE_EVENT; } else { @@ -477,13 +566,14 @@ int lttng_enable_channel(struct lttng_handle *handle, { struct lttcomm_session_msg lsm; - if (!handle) { + /* + * NULL arguments are forbidden. No default values. + */ + if (handle == NULL || chan == NULL) { return -1; } - if (chan) { - memcpy(&lsm.u.channel.chan, chan, sizeof(lsm.u.channel.chan)); - } + memcpy(&lsm.u.channel.chan, chan, sizeof(lsm.u.channel.chan)); lsm.cmd_type = LTTNG_ENABLE_CHANNEL; @@ -502,17 +592,16 @@ int lttng_disable_channel(struct lttng_handle *handle, const char *name) { struct lttcomm_session_msg lsm; - if (!handle) { + /* Safety check. Both are mandatory */ + if (handle == NULL || name == NULL) { return -1; } - if (name) { - copy_string(lsm.u.disable.channel_name, name, - sizeof(lsm.u.disable.channel_name)); - } - lsm.cmd_type = LTTNG_DISABLE_CHANNEL; + copy_string(lsm.u.disable.channel_name, name, + sizeof(lsm.u.disable.channel_name)); + copy_lttng_domain(&lsm.domain, &handle->domain); copy_string(lsm.session.name, handle->session_name, @@ -533,7 +622,7 @@ int lttng_list_tracepoints(struct lttng_handle *handle, int ret; struct lttcomm_session_msg lsm; - if (!handle) { + if (handle == NULL) { return -1; } @@ -551,7 +640,7 @@ int lttng_list_tracepoints(struct lttng_handle *handle, /* * Return a human readable string of code */ -const char *lttng_get_readable_code(int code) +const char *lttng_strerror(int code) { if (code > -LTTCOMM_OK) { return "Ended with errors"; @@ -581,7 +670,7 @@ int lttng_destroy_session(struct lttng_handle *handle) { struct lttcomm_session_msg lsm; - if (!handle) { + if (handle == NULL) { return -1; } @@ -621,7 +710,7 @@ int lttng_list_domains(struct lttng_handle *handle, int ret; struct lttcomm_session_msg lsm; - if (!handle) { + if (handle == NULL) { return -1; } @@ -647,7 +736,7 @@ int lttng_list_channels(struct lttng_handle *handle, int ret; struct lttcomm_session_msg lsm; - if (!handle) { + if (handle == NULL) { return -1; } @@ -674,7 +763,8 @@ int lttng_list_events(struct lttng_handle *handle, int ret; struct lttcomm_session_msg lsm; - if (!handle) { + /* Safety check. An handle and channel name are mandatory */ + if (handle == NULL || channel_name == NULL) { return -1; } @@ -695,13 +785,15 @@ int lttng_list_events(struct lttng_handle *handle, } /* - * lttng_set_tracing_group - * - * Set tracing group variable with name. This function - * allocate memory pointed by tracing_group. + * Set tracing group variable with name. This function allocate memory pointed + * by tracing_group. */ int lttng_set_tracing_group(const char *name) { + if (name == NULL) { + return -1; + } + if (asprintf(&tracing_group, "%s", name) < 0) { return -ENOMEM; } @@ -717,7 +809,8 @@ int lttng_calibrate(struct lttng_handle *handle, { struct lttcomm_session_msg lsm; - if (!handle) { + /* Safety check. NULL pointer are forbidden */ + if (handle == NULL || calibrate == NULL) { return -1; } @@ -730,11 +823,50 @@ int lttng_calibrate(struct lttng_handle *handle, } /* - * lttng_check_session_daemon + * Set default channel attributes. + */ +void lttng_channel_set_default_attr(struct lttng_domain *domain, + struct lttng_channel_attr *attr) +{ + /* Safety check */ + if (attr == NULL || domain == NULL) { + return; + } + + switch (domain->type) { + case LTTNG_DOMAIN_KERNEL: + attr->overwrite = DEFAULT_CHANNEL_OVERWRITE; + attr->switch_timer_interval = DEFAULT_CHANNEL_SWITCH_TIMER; + attr->read_timer_interval = DEFAULT_CHANNEL_READ_TIMER; + + attr->subbuf_size = DEFAULT_KERNEL_CHANNEL_SUBBUF_SIZE; + attr->num_subbuf = DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM; + attr->output = DEFAULT_KERNEL_CHANNEL_OUTPUT; + break; + case LTTNG_DOMAIN_UST: + case LTTNG_DOMAIN_UST_EXEC_NAME: + case LTTNG_DOMAIN_UST_PID: + case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: + attr->overwrite = DEFAULT_CHANNEL_OVERWRITE; + attr->switch_timer_interval = DEFAULT_CHANNEL_SWITCH_TIMER; + attr->read_timer_interval = DEFAULT_CHANNEL_READ_TIMER; + + attr->subbuf_size = DEFAULT_UST_CHANNEL_SUBBUF_SIZE; + attr->num_subbuf = DEFAULT_UST_CHANNEL_SUBBUF_NUM; + attr->output = DEFAULT_UST_CHANNEL_OUTPUT; + break; + default: + /* Default behavior */ + memset(attr, 0, sizeof(struct lttng_channel_attr)); + break; + } +} + +/* + * Check if session daemon is alive. * - * Yes, return 1 - * No, return 0 - * Error, return negative value + * Return 1 if alive or 0 if not. + * On error return -1 */ int lttng_session_daemon_alive(void) { @@ -746,21 +878,16 @@ int lttng_session_daemon_alive(void) return ret; } - /* If socket exist, we check if the daemon listens to connect. */ - ret = access(sessiond_sock_path, F_OK); - if (ret < 0) { - /* Not alive */ - return 0; + if (strlen(sessiond_sock_path) == 0) { + /* No socket path set. Weird error */ + return -1; } - ret = lttcomm_connect_unix_sock(sessiond_sock_path); + ret = try_connect_sessiond(sessiond_sock_path); if (ret < 0) { /* Not alive */ return 0; } - ret = lttcomm_close_unix_sock(ret); - if (ret < 0) - perror("lttcomm_close_unix_sock"); /* Is alive */ return 1;