consumer->relay_major_version = control_sock->major;
consumer->relay_minor_version = control_sock->minor;
- ret = relayd_get_configuration(control_sock, 0, result_flags, nullptr);
+ ret = relayd_get_configuration(control_sock,
+ LTTCOMM_RELAYD_CONFIGURATION_QUERY_FLAG_SUPPORTED_TRACE_FORMAT,
+ result_flags, &supported_trace_format);
if (ret < 0) {
ERR("Unable to get relayd configuration");
status = LTTNG_ERR_RELAYD_CONNECT_FAIL;
return ret;
}
+enum lttng_error_code cmd_execute_trace_format_support_query(
+ struct command_ctx& cmd_ctx, int sock, int& sock_error)
+{
+ int ret;
+ enum lttng_error_code ret_code;
+ struct lttng_payload query_payload;
+ size_t payload_len, offset = 0;
+ ssize_t sock_recv_len, consumed;
+
+ lttng::trace_format_descriptor::uptr trace_format;
+
+ lttng_payload_init(&query_payload);
+
+ /* Receive the payload */
+ payload_len = (size_t) cmd_ctx.lsm.u.trace_format_support_query.trace_format_length +
+ cmd_ctx.lsm.u.trace_format_support_query.type_payload_length;
+ ret = lttng_dynamic_buffer_set_size(&query_payload.buffer, payload_len);
+ if (ret) {
+ ret_code = LTTNG_ERR_NOMEM;
+ }
+
+ sock_recv_len = lttcomm_recv_unix_sock(sock, query_payload.buffer.data, payload_len);
+ if (sock_recv_len < 0 || sock_recv_len != payload_len) {
+ ERR("Failed to receive error query in command payload");
+ sock_error = 1;
+ ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+ goto end;
+ }
+
+ /* Receive fds, if any. */
+ if (cmd_ctx.lsm.fd_count > 0) {
+ sock_recv_len = lttcomm_recv_payload_fds_unix_sock(
+ sock, cmd_ctx.lsm.fd_count, &query_payload);
+ if (sock_recv_len > 0 && sock_recv_len != cmd_ctx.lsm.fd_count * sizeof(int)) {
+ ERR("Failed to receive all file descriptors for error query in command payload: expected fd count = %u, ret = %d",
+ cmd_ctx.lsm.fd_count, (int) ret);
+ ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+ sock_error = 1;
+ goto end;
+ } else if (sock_recv_len <= 0) {
+ ERR("Failed to receive file descriptors for error query in command payload: expected fd count = %u, ret = %d",
+ cmd_ctx.lsm.fd_count, (int) ret);
+ ret_code = LTTNG_ERR_FATAL;
+ sock_error = 1;
+ goto end;
+ }
+ }
+
+ /* Deserialize trace_format_descriptor. */
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(&query_payload, offset, -1);
+ if (!lttng_payload_view_is_valid(&view)) {
+ ret = LTTNG_ERR_INVALID_PROTOCOL;
+ goto end;
+ }
+
+ consumed = lttng::trace_format_descriptor::create_from_payload(&view, trace_format);
+
+ if (consumed != cmd_ctx.lsm.u.trace_format_support_query.trace_format_length) {
+ ERR("Invalid trace format descriptor received as part of command payload");
+ ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+ goto end;
+ }
+ offset += consumed;
+ }
+
+ switch (cmd_ctx.lsm.u.trace_format_support_query.query_type) {
+ case 0:
+ {
+ if (cmd_ctx.lsm.domain.type != LTTNG_DOMAIN_KERNEL) {
+ /* UST supports all trace format*/
+ ret_code = LTTNG_OK;
+ goto end;
+ }
+ ret_code = kernel_domain_check_trace_format_requirements(*trace_format);
+ break;
+ }
+ case 1:
+ {
+ struct lttcomm_relayd_sock *relay_sock = nullptr;
+ struct lttng_uri uri;
+ uint64_t result_flags = 0;
+ uint64_t supported_trace_format = 0;
+ struct lttng_payload_view view = lttng_payload_view_from_payload(&query_payload,
+ offset,
+ cmd_ctx.lsm.u.trace_format_support_query.type_payload_length);
+ if (!lttng_payload_view_is_valid(&view)) {
+ ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+ goto end;
+ }
+
+ memcpy(&uri, view.buffer.data, sizeof(uri));
+ ret_code = create_connect_relayd(&uri, &relay_sock);
+ if (ret_code != LTTNG_OK) {
+ goto end;
+ }
+ LTTNG_ASSERT(sock);
+
+ ret_code = relayd_get_configuration(relay_sock,
+ LTTCOMM_RELAYD_CONFIGURATION_QUERY_FLAG_SUPPORTED_TRACE_FORMAT,
+ result_flags, &supported_trace_format);
+ if (ret_code != LTTNG_OK) {
+ goto end;
+ }
+
+ if (!(supported_trace_format & trace_format->relayd_type())) {
+ ERR("Relayd does not support the requested trace format");
+ ret_code = LTTNG_ERR_TRACE_FORMAT_UNSUPPORTED_RELAY_DAEMON;
+ goto end;
+ }
+
+ ret_code = LTTNG_OK;
+ break;
+ }
+ default:
+ {
+ ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+ break;
+ }
+ }
+end:
+ lttng_payload_reset(&query_payload);
+ return ret_code;
+}
+
/* Wait for a given path to be removed before continuing. */
static enum lttng_error_code wait_on_path(void *path_data)
{