return ret;
}
+static int recv_sessiond_optional_data(size_t len, void **user_buf,
+ size_t *user_len)
+{
+ int ret = 0;
+ void *buf = NULL;
+
+ if (len) {
+ if (!user_len) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ buf = zmalloc(len);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto end;
+ }
+
+ ret = recv_data_sessiond(buf, len);
+ if (ret < 0) {
+ goto end;
+ }
+
+ if (!user_buf) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ /* Move ownership of command header buffer to user. */
+ *user_buf = buf;
+ buf = NULL;
+ *user_len = len;
+ } else {
+ /* No command header. */
+ if (user_len) {
+ *user_len = 0;
+ }
+
+ if (user_buf) {
+ *user_buf = NULL;
+ }
+ }
+
+end:
+ free(buf);
+ return ret;
+}
+
/*
* Ask the session daemon a specific command and put the data into buf.
* Takes extra var. len. data as input to send to the session daemon.
*/
LTTNG_HIDDEN
int lttng_ctl_ask_sessiond_varlen(struct lttcomm_session_msg *lsm,
- const void *vardata, size_t varlen, void **buf)
+ const void *vardata, size_t vardata_len,
+ void **user_payload_buf, void **user_cmd_header_buf,
+ size_t *user_cmd_header_len)
{
int ret;
- size_t size;
- void *data = NULL;
+ size_t payload_len;
struct lttcomm_lttng_msg llm;
ret = connect_sessiond();
goto end;
}
/* Send var len data */
- ret = send_session_varlen(vardata, varlen);
+ ret = send_session_varlen(vardata, vardata_len);
if (ret < 0) {
/* Ret value is a valid lttng error code. */
goto end;
goto end;
}
- size = llm.data_size;
- if (size == 0) {
- /* If client free with size 0 */
- if (buf != NULL) {
- *buf = NULL;
- }
- ret = 0;
- goto end;
- }
-
- data = zmalloc(size);
- if (!data) {
- ret = -ENOMEM;
- goto end;
- }
-
- /* Get payload data */
- ret = recv_data_sessiond(data, size);
+ /* Get command header from data transmission */
+ ret = recv_sessiond_optional_data(llm.cmd_header_size,
+ user_cmd_header_buf, user_cmd_header_len);
if (ret < 0) {
- free(data);
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 = -LTTNG_ERR_INVALID;
- free(data);
+ /* Get payload from data transmission */
+ ret = recv_sessiond_optional_data(llm.data_size, user_payload_buf,
+ &payload_len);
+ if (ret < 0) {
goto end;
}
- *buf = data;
- ret = size;
+ ret = llm.data_size;
end:
disconnect_sessiond();
lsm.u.context.ctx.u.app_ctx.provider_name = NULL;
lsm.u.context.ctx.u.app_ctx.ctx_name = NULL;
- ret = lttng_ctl_ask_sessiond_varlen(&lsm, buf, len, NULL);
+ ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, buf, len, NULL);
end:
free(buf);
return ret;
lsm.u.enable.bytecode_len);
}
- ret = lttng_ctl_ask_sessiond_varlen(&lsm, varlen_data,
+ ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, varlen_data,
(LTTNG_SYMBOL_NAME_LEN * lsm.u.enable.exclusion_count) +
lsm.u.enable.bytecode_len + lsm.u.enable.expression_len,
NULL);
lsm.u.disable.bytecode_len);
}
- ret = lttng_ctl_ask_sessiond_varlen(&lsm, varlen_data,
+ ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, varlen_data,
lsm.u.disable.bytecode_len + lsm.u.disable.expression_len, NULL);
free(varlen_data);
lsm.u.uri.size = size;
- ret = lttng_ctl_ask_sessiond_varlen(&lsm, uris,
+ ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, uris,
sizeof(struct lttng_uri) * size, NULL);
free(uris);
{
int ret;
struct lttcomm_session_msg lsm;
+ struct lttcomm_event_command_header *cmd_header = NULL;
+ size_t cmd_header_len;
+ uint32_t nb_events, i;
+ void *extended_at;
/* Safety check. An handle and channel name are mandatory */
if (handle == NULL || channel_name == NULL) {
sizeof(lsm.session.name));
lttng_ctl_copy_string(lsm.u.list.channel_name, channel_name,
sizeof(lsm.u.list.channel_name));
-
lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain);
- ret = lttng_ctl_ask_sessiond(&lsm, (void**) events);
+ ret = lttng_ctl_ask_sessiond_varlen(&lsm, NULL, 0, (void **) events,
+ (void **) &cmd_header, &cmd_header_len);
if (ret < 0) {
- return ret;
+ goto error;
}
- return ret / sizeof(struct lttng_event);
+ /* Set number of events and free command header */
+ nb_events = cmd_header->nb_events;
+ if (nb_events > INT_MAX) {
+ ret = -EOVERFLOW;
+ goto error;
+ }
+ ret = (int) nb_events;
+ free(cmd_header);
+ cmd_header = NULL;
+
+ /* Set extended info pointers */
+ extended_at = ((void*) (*events)) +
+ nb_events * sizeof(struct lttng_event);
+
+ for (i = 0; i < nb_events; i++) {
+ struct lttcomm_event_extended_header *ext_header;
+ struct lttng_event *event = &(*events)[i];
+
+ event->extended.ptr = extended_at;
+ ext_header =
+ (struct lttcomm_event_extended_header *) extended_at;
+ extended_at += sizeof(*ext_header);
+ extended_at += ext_header->filter_len;
+ }
+
+ return ret;
+error:
+ free(cmd_header);
+ free(*events);
+ return ret;
}
+
/*
* Sets the tracing_group variable with name.
* This function allocates memory pointed to by tracing_group.
lsm.u.uri.size = size;
- ret = lttng_ctl_ask_sessiond_varlen(&lsm, uris,
+ ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, uris,
sizeof(struct lttng_uri) * size, NULL);
free(uris);
}
}
- ret = lttng_ctl_ask_sessiond_varlen(&lsm, uris,
+ ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, uris,
sizeof(struct lttng_uri) * size, NULL);
error:
lsm.u.uri.size = size;
- ret = lttng_ctl_ask_sessiond_varlen(&lsm, uris,
+ ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, uris,
sizeof(struct lttng_uri) * size, NULL);
free(uris);
lsm.u.session_live.nb_uri = size;
lsm.u.session_live.timer_interval = timer_interval;
- ret = lttng_ctl_ask_sessiond_varlen(&lsm, uris,
+ ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, uris,
sizeof(struct lttng_uri) * size, NULL);
end: