Fix: Use unix socket peercred for pid, uid, gid credentials
[lttng-ust.git] / liblttng-ust-comm / lttng-ust-comm.c
index 3d1c65038295062559db6dd415fe2b03304d5ec2..d2057daf95d9320b095e6a67c2d3b644c7b16f32 100644 (file)
@@ -17,8 +17,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#define _GNU_SOURCE
 #include <limits.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -54,6 +54,11 @@ static
 int serialize_one_field(struct lttng_session *session,
                struct ustctl_field *fields, size_t *iter_output,
                const struct lttng_event_field *lf);
+static
+int serialize_fields(struct lttng_session *session,
+               struct ustctl_field *ustctl_fields,
+               size_t *iter_output, size_t nr_lttng_fields,
+               const struct lttng_event_field *lttng_fields);
 
 /*
  * Human readable error message.
@@ -71,6 +76,8 @@ static const char *ustcomm_readable_code[] = {
        [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_INVAL_MAGIC) ] = "Invalid magic number",
        [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_INVAL_SOCKET_TYPE) ] = "Invalid socket type",
        [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_UNSUP_MAJOR) ] = "Unsupported major version",
+       [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_PEERCRED) ] = "Cannot get unix socket peer credentials",
+       [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_PEERCRED_PID) ] = "Peer credentials PID is invalid. Socket appears to belong to a distinct, non-nested pid namespace.",
 };
 
 /*
@@ -106,6 +113,7 @@ int ustcomm_connect_unix_sock(const char *pathname, long timeout)
        /*
         * libust threads require the close-on-exec flag for all
         * resources so it does not leak file descriptors upon exec.
+        * SOCK_CLOEXEC is not used since it is linux specific.
         */
        fd = socket(PF_UNIX, SOCK_STREAM, 0);
        if (fd < 0) {
@@ -438,8 +446,6 @@ ssize_t ustcomm_send_fds_unix_sock(int sock, int *fds, size_t nb_fd)
 /*
  * Recv a message accompanied by fd(s) from a unix socket.
  *
- * Returns the size of received data, or negative error value.
- *
  * Expect at most "nb_fd" file descriptors. Returns the number of fd
  * actually received in nb_fd.
  * Returns -EPIPE on orderly shutdown.
@@ -453,6 +459,7 @@ ssize_t ustcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd)
        char recv_fd[CMSG_SPACE(sizeof_fds)];
        struct msghdr msg;
        char dummy;
+       int i;
 
        memset(&msg, 0, sizeof(msg));
 
@@ -508,8 +515,19 @@ ssize_t ustcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd)
                ret = -1;
                goto end;
        }
+
        memcpy(fds, CMSG_DATA(cmsg), sizeof_fds);
-       ret = sizeof_fds;
+
+       /* Set FD_CLOEXEC */
+       for (i = 0; i < nb_fd; i++) {
+               ret = fcntl(fds[i], F_SETFD, FD_CLOEXEC);
+               if (ret < 0) {
+                       PERROR("fcntl failed to set FD_CLOEXEC on fd %d",
+                              fds[i]);
+               }
+       }
+
+       ret = nb_fd;
 end:
        return ret;
 }
@@ -630,12 +648,12 @@ ssize_t ustcomm_recv_channel_from_sessiond(int sock,
 
        ret = lttng_ust_add_fd_to_tracker(wakeup_fd);
        if (ret < 0) {
-               lttng_ust_unlock_fd_tracker();
                ret = close(wakeup_fd);
                if (ret) {
                        PERROR("close on wakeup_fd");
                }
                len = -EIO;
+               lttng_ust_unlock_fd_tracker();
                goto error_recv;
        }
 
@@ -652,6 +670,46 @@ error_check:
        return len;
 }
 
+ssize_t ustcomm_recv_event_notifier_notif_fd_from_sessiond(int sock,
+               int *_event_notifier_notif_fd)
+{
+       ssize_t nr_fd;
+       int event_notifier_notif_fd, ret;
+
+       /* Receive event_notifier notification fd */
+       lttng_ust_lock_fd_tracker();
+       nr_fd = ustcomm_recv_fds_unix_sock(sock, &event_notifier_notif_fd, 1);
+       if (nr_fd <= 0) {
+               lttng_ust_unlock_fd_tracker();
+               if (nr_fd < 0) {
+                       ret = nr_fd;
+                       goto error;
+               } else {
+                       ret = -EIO;
+                       goto error;
+               }
+       }
+
+       ret = lttng_ust_add_fd_to_tracker(event_notifier_notif_fd);
+       if (ret < 0) {
+               ret = close(event_notifier_notif_fd);
+               if (ret) {
+                       PERROR("close on event_notifier notif fd");
+               }
+               ret = -EIO;
+               lttng_ust_unlock_fd_tracker();
+               goto error;
+       }
+
+       *_event_notifier_notif_fd = ret;
+       lttng_ust_unlock_fd_tracker();
+
+       ret = nr_fd;
+
+error:
+       return ret;
+}
+
 int ustcomm_recv_stream_from_sessiond(int sock,
                uint64_t *memory_map_size,
                int *shm_fd, int *wakeup_fd)
@@ -676,19 +734,18 @@ int ustcomm_recv_stream_from_sessiond(int sock,
 
        ret = lttng_ust_add_fd_to_tracker(fds[0]);
        if (ret < 0) {
-               lttng_ust_unlock_fd_tracker();
                ret = close(fds[0]);
                if (ret) {
                        PERROR("close on received shm_fd");
                }
                ret = -EIO;
+               lttng_ust_unlock_fd_tracker();
                goto error;
        }
        *shm_fd = ret;
 
        ret = lttng_ust_add_fd_to_tracker(fds[1]);
        if (ret < 0) {
-               lttng_ust_unlock_fd_tracker();
                ret = close(*shm_fd);
                if (ret) {
                        PERROR("close on shm_fd");
@@ -699,6 +756,7 @@ int ustcomm_recv_stream_from_sessiond(int sock,
                        PERROR("close on received wakeup_fd");
                }
                ret = -EIO;
+               lttng_ust_unlock_fd_tracker();
                goto error;
        }
        *wakeup_fd = ret;
@@ -709,6 +767,75 @@ error:
        return ret;
 }
 
+ssize_t ustcomm_recv_counter_from_sessiond(int sock,
+               void **_counter_data, uint64_t var_len)
+{
+       void *counter_data;
+       ssize_t len;
+
+       if (var_len > LTTNG_UST_COUNTER_DATA_MAX_LEN) {
+               len = -EINVAL;
+               goto error_check;
+       }
+       /* Receive variable length data */
+       counter_data = zmalloc(var_len);
+       if (!counter_data) {
+               len = -ENOMEM;
+               goto error_alloc;
+       }
+       len = ustcomm_recv_unix_sock(sock, counter_data, var_len);
+       if (len != var_len) {
+               goto error_recv;
+       }
+       *_counter_data = counter_data;
+       return len;
+
+error_recv:
+       free(counter_data);
+error_alloc:
+error_check:
+       return len;
+}
+
+int ustcomm_recv_counter_shm_from_sessiond(int sock,
+               int *shm_fd)
+{
+       ssize_t len;
+       int ret;
+       int fds[1];
+
+       /* recv shm fd fd */
+       lttng_ust_lock_fd_tracker();
+       len = ustcomm_recv_fds_unix_sock(sock, fds, 1);
+       if (len <= 0) {
+               lttng_ust_unlock_fd_tracker();
+               if (len < 0) {
+                       ret = len;
+                       goto error;
+               } else {
+                       ret = -EIO;
+                       goto error;
+               }
+       }
+
+       ret = lttng_ust_add_fd_to_tracker(fds[0]);
+       if (ret < 0) {
+               ret = close(fds[0]);
+               if (ret) {
+                       PERROR("close on received shm_fd");
+               }
+               ret = -EIO;
+               lttng_ust_unlock_fd_tracker();
+               goto error;
+       }
+       *shm_fd = ret;
+       lttng_ust_unlock_fd_tracker();
+       return 0;
+
+error:
+       return ret;
+}
+
 /*
  * Returns 0 on success, negative error value on error.
  */
@@ -738,7 +865,7 @@ int ustcomm_send_reg_msg(int sock,
        reg_msg.uint64_t_alignment = uint64_t_alignment;
        reg_msg.long_alignment = long_alignment;
        reg_msg.socket_type = type;
-       lttng_ust_getprocname(reg_msg.name);
+       lttng_pthread_getname_np(reg_msg.name, LTTNG_UST_ABI_PROCNAME_LEN);
        memset(reg_msg.padding, 0, sizeof(reg_msg.padding));
 
        len = ustcomm_send_unix_sock(sock, &reg_msg, sizeof(reg_msg));
@@ -761,8 +888,18 @@ ssize_t count_one_type(const struct lttng_type *lt)
        case atype_sequence:
                return 1;
        case atype_struct:
-               //TODO: implement non-empty struct.
-               return 1;
+               return count_fields_recursive(lt->u.legacy._struct.nr_fields,
+                               lt->u.legacy._struct.fields) + 1;
+       case atype_enum_nestable:
+               return count_one_type(lt->u.enum_nestable.container_type) + 1;
+       case atype_array_nestable:
+               return count_one_type(lt->u.array_nestable.elem_type) + 1;
+       case atype_sequence_nestable:
+               return count_one_type(lt->u.sequence_nestable.elem_type) + 1;
+       case atype_struct_nestable:
+               return count_fields_recursive(lt->u.struct_nestable.nr_fields,
+                               lt->u.struct_nestable.fields) + 1;
+
        case atype_dynamic:
        {
                const struct lttng_event_field *choices;
@@ -774,11 +911,12 @@ ssize_t count_one_type(const struct lttng_type *lt)
                if (ret)
                        return ret;
                /*
-                * One field for enum, one field for variant, and
+                * Two fields for enum, one field for variant, and
                 * one field per choice.
                 */
-               return count_fields_recursive(nr_choices, choices) + 2;
+               return count_fields_recursive(nr_choices, choices) + 3;
        }
+
        default:
                return -EINVAL;
        }
@@ -853,12 +991,15 @@ static
 int serialize_integer_type(struct ustctl_integer_type *uit,
                const struct lttng_integer_type *lit)
 {
+       int32_t encoding;
+
        uit->size = lit->size;
        uit->signedness = lit->signedness;
        uit->reverse_byte_order = lit->reverse_byte_order;
        uit->base = lit->base;
-       if (serialize_string_encoding(&uit->encoding, lit->encoding))
+       if (serialize_string_encoding(&encoding, lit->encoding))
                return -EINVAL;
+       uit->encoding = encoding;
        uit->alignment = lit->alignment;
        return 0;
 }
@@ -880,9 +1021,11 @@ int serialize_basic_type(struct lttng_session *session,
        }
        case atype_string:
        {
-               if (serialize_string_encoding(&ubt->string.encoding,
-                               lbt->string.encoding))
+               int32_t encoding;
+
+               if (serialize_string_encoding(&encoding, lbt->string.encoding))
                        return -EINVAL;
+               ubt->string.encoding = encoding;
                *uatype = ustctl_atype_string;
                break;
        }
@@ -911,8 +1054,7 @@ int serialize_basic_type(struct lttng_session *session,
                if (session) {
                        const struct lttng_enum *_enum;
 
-                       _enum = lttng_ust_enum_get(session,
-                                       lbt->enumeration.desc->name);
+                       _enum = lttng_ust_enum_get_from_desc(session, lbt->enumeration.desc);
                        if (!_enum)
                                return -EINVAL;
                        ubt->enumeration.id = _enum->id;
@@ -923,7 +1065,10 @@ int serialize_basic_type(struct lttng_session *session,
                break;
        }
        case atype_array:
+       case atype_array_nestable:
        case atype_sequence:
+       case atype_sequence_nestable:
+       case atype_enum_nestable:
        default:
                return -EINVAL;
        }
@@ -933,7 +1078,7 @@ int serialize_basic_type(struct lttng_session *session,
 static
 int serialize_dynamic_type(struct lttng_session *session,
                struct ustctl_field *fields, size_t *iter_output,
-               const struct lttng_event_field *lf)
+               const char *field_name)
 {
        const struct lttng_event_field *choices;
        char tag_field_name[LTTNG_UST_SYM_NAME_LEN];
@@ -951,7 +1096,7 @@ int serialize_dynamic_type(struct lttng_session *session,
        tag_type = &tag_field_generic->type;
 
        /* Serialize enum field. */
-       strncpy(tag_field_name, lf->name, LTTNG_UST_SYM_NAME_LEN);
+       strncpy(tag_field_name, field_name, LTTNG_UST_SYM_NAME_LEN);
        tag_field_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
        strncat(tag_field_name,
                "_tag",
@@ -968,14 +1113,15 @@ int serialize_dynamic_type(struct lttng_session *session,
        if (ret)
                return ret;
 
-       strncpy(uf->name, lf->name, LTTNG_UST_SYM_NAME_LEN);
+       strncpy(uf->name, field_name, LTTNG_UST_SYM_NAME_LEN);
        uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
        uf->type.atype = ustctl_atype_variant;
-       uf->type.u.variant.nr_choices = nr_choices;
-       strncpy(uf->type.u.variant.tag_name,
+       uf->type.u.variant_nestable.nr_choices = nr_choices;
+       strncpy(uf->type.u.variant_nestable.tag_name,
                tag_field_name,
                LTTNG_UST_SYM_NAME_LEN);
-       uf->type.u.variant.tag_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+       uf->type.u.variant_nestable.tag_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+       uf->type.u.variant_nestable.alignment = 0;
        (*iter_output)++;
 
        /* Serialize choice fields after variant. */
@@ -989,16 +1135,16 @@ int serialize_dynamic_type(struct lttng_session *session,
 }
 
 static
-int serialize_one_field(struct lttng_session *session,
+int serialize_one_type(struct lttng_session *session,
                struct ustctl_field *fields, size_t *iter_output,
-               const struct lttng_event_field *lf)
+               const char *field_name, const struct lttng_type *lt)
 {
-       const struct lttng_type *lt = &lf->type;
        int ret;
 
-       /* skip 'nowrite' fields */
-       if (lf->nowrite)
-               return 0;
+       /*
+        * Serializing a type (rather than a field) generates a ustctl_field
+        * entry with 0-length name.
+        */
 
        switch (lt->atype) {
        case atype_integer:
@@ -1008,13 +1154,19 @@ int serialize_one_field(struct lttng_session *session,
        {
                struct ustctl_field *uf = &fields[*iter_output];
                struct ustctl_type *ut = &uf->type;
+               enum ustctl_abstract_types atype;
 
-               strncpy(uf->name, lf->name, LTTNG_UST_SYM_NAME_LEN);
-               uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
-               ret = serialize_basic_type(session, &ut->atype, lt->atype,
-                       &ut->u.basic, &lt->u.basic);
+               if (field_name) {
+                       strncpy(uf->name, field_name, LTTNG_UST_SYM_NAME_LEN);
+                       uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               } else {
+                       uf->name[0] = '\0';
+               }
+               ret = serialize_basic_type(session, &atype, lt->atype,
+                       &ut->u.legacy.basic, &lt->u.legacy.basic);
                if (ret)
                        return ret;
+               ut->atype = atype;
                (*iter_output)++;
                break;
        }
@@ -1024,51 +1176,109 @@ int serialize_one_field(struct lttng_session *session,
                struct ustctl_type *ut = &uf->type;
                struct ustctl_basic_type *ubt;
                const struct lttng_basic_type *lbt;
+               enum ustctl_abstract_types atype;
 
-               strncpy(uf->name, lf->name, LTTNG_UST_SYM_NAME_LEN);
-               uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
-               uf->type.atype = ustctl_atype_array;
-               ubt = &ut->u.array.elem_type;
-               lbt = &lt->u.array.elem_type;
-               ut->u.array.length = lt->u.array.length;
-               ret = serialize_basic_type(session, &ubt->atype, lbt->atype,
+               if (field_name) {
+                       strncpy(uf->name, field_name, LTTNG_UST_SYM_NAME_LEN);
+                       uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               } else {
+                       uf->name[0] = '\0';
+               }
+               ut->atype = ustctl_atype_array;
+               ubt = &ut->u.legacy.array.elem_type;
+               lbt = &lt->u.legacy.array.elem_type;
+               ut->u.legacy.array.length = lt->u.legacy.array.length;
+               ret = serialize_basic_type(session, &atype, lbt->atype,
                        &ubt->u.basic, &lbt->u.basic);
                if (ret)
                        return -EINVAL;
-               ut->atype = ustctl_atype_array;
+               ubt->atype = atype;
                (*iter_output)++;
                break;
        }
+       case atype_array_nestable:
+       {
+               struct ustctl_field *uf = &fields[*iter_output];
+               struct ustctl_type *ut = &uf->type;
+
+               if (field_name) {
+                       strncpy(uf->name, field_name, LTTNG_UST_SYM_NAME_LEN);
+                       uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               } else {
+                       uf->name[0] = '\0';
+               }
+               ut->atype = ustctl_atype_array_nestable;
+               ut->u.array_nestable.length = lt->u.array_nestable.length;
+               ut->u.array_nestable.alignment = lt->u.array_nestable.alignment;
+               (*iter_output)++;
+
+               ret = serialize_one_type(session, fields, iter_output, NULL,
+                               lt->u.array_nestable.elem_type);
+               if (ret)
+                       return -EINVAL;
+               break;
+       }
        case atype_sequence:
        {
                struct ustctl_field *uf = &fields[*iter_output];
                struct ustctl_type *ut = &uf->type;
                struct ustctl_basic_type *ubt;
                const struct lttng_basic_type *lbt;
-               int ret;
+               enum ustctl_abstract_types atype;
 
-               strncpy(uf->name, lf->name, LTTNG_UST_SYM_NAME_LEN);
-               uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               if (field_name) {
+                       strncpy(uf->name, field_name, LTTNG_UST_SYM_NAME_LEN);
+                       uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               } else {
+                       uf->name[0] = '\0';
+               }
                uf->type.atype = ustctl_atype_sequence;
-               ubt = &ut->u.sequence.length_type;
-               lbt = &lt->u.sequence.length_type;
-               ret = serialize_basic_type(session, &ubt->atype, lbt->atype,
+               ubt = &ut->u.legacy.sequence.length_type;
+               lbt = &lt->u.legacy.sequence.length_type;
+               ret = serialize_basic_type(session, &atype, lbt->atype,
                        &ubt->u.basic, &lbt->u.basic);
                if (ret)
                        return -EINVAL;
-               ubt = &ut->u.sequence.elem_type;
-               lbt = &lt->u.sequence.elem_type;
-               ret = serialize_basic_type(session, &ubt->atype, lbt->atype,
+               ubt->atype = atype;
+               ubt = &ut->u.legacy.sequence.elem_type;
+               lbt = &lt->u.legacy.sequence.elem_type;
+               ret = serialize_basic_type(session, &atype, lbt->atype,
                        &ubt->u.basic, &lbt->u.basic);
                if (ret)
                        return -EINVAL;
-               ut->atype = ustctl_atype_sequence;
+               ubt->atype = atype;
                (*iter_output)++;
                break;
        }
+       case atype_sequence_nestable:
+       {
+               struct ustctl_field *uf = &fields[*iter_output];
+               struct ustctl_type *ut = &uf->type;
+
+               if (field_name) {
+                       strncpy(uf->name, field_name, LTTNG_UST_SYM_NAME_LEN);
+                       uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               } else {
+                       uf->name[0] = '\0';
+               }
+               ut->atype = ustctl_atype_sequence_nestable;
+               strncpy(ut->u.sequence_nestable.length_name,
+                       lt->u.sequence_nestable.length_name,
+                       LTTNG_UST_SYM_NAME_LEN);
+               ut->u.sequence_nestable.length_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               ut->u.sequence_nestable.alignment = lt->u.sequence_nestable.alignment;
+               (*iter_output)++;
+
+               ret = serialize_one_type(session, fields, iter_output, NULL,
+                               lt->u.sequence_nestable.elem_type);
+               if (ret)
+                       return -EINVAL;
+               break;
+       }
        case atype_dynamic:
        {
-               ret = serialize_dynamic_type(session, fields, iter_output, lf);
+               ret = serialize_dynamic_type(session, fields, iter_output,
+                               field_name);
                if (ret)
                        return -EINVAL;
                break;
@@ -1077,17 +1287,76 @@ int serialize_one_field(struct lttng_session *session,
        {
                struct ustctl_field *uf = &fields[*iter_output];
 
-               /*
-                * TODO: add support for non-empty struct.
-                */
-               if (lf->type.u._struct.nr_fields != 0) {
-                       return -EINVAL;
+               if (field_name) {
+                       strncpy(uf->name, field_name, LTTNG_UST_SYM_NAME_LEN);
+                       uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               } else {
+                       uf->name[0] = '\0';
                }
-               strncpy(uf->name, lf->name, LTTNG_UST_SYM_NAME_LEN);
-               uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
                uf->type.atype = ustctl_atype_struct;
-               uf->type.u._struct.nr_fields = 0;
+               uf->type.u.legacy._struct.nr_fields = lt->u.legacy._struct.nr_fields;
                (*iter_output)++;
+
+               ret = serialize_fields(session, fields, iter_output,
+                               lt->u.legacy._struct.nr_fields,
+                               lt->u.legacy._struct.fields);
+               if (ret)
+                       return -EINVAL;
+               break;
+       }
+       case atype_struct_nestable:
+       {
+               struct ustctl_field *uf = &fields[*iter_output];
+
+               if (field_name) {
+                       strncpy(uf->name, field_name, LTTNG_UST_SYM_NAME_LEN);
+                       uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               } else {
+                       uf->name[0] = '\0';
+               }
+               uf->type.atype = ustctl_atype_struct_nestable;
+               uf->type.u.struct_nestable.nr_fields = lt->u.struct_nestable.nr_fields;
+               uf->type.u.struct_nestable.alignment = lt->u.struct_nestable.alignment;
+               (*iter_output)++;
+
+               ret = serialize_fields(session, fields, iter_output,
+                               lt->u.struct_nestable.nr_fields,
+                               lt->u.struct_nestable.fields);
+               if (ret)
+                       return -EINVAL;
+               break;
+       }
+       case atype_enum_nestable:
+       {
+               struct ustctl_field *uf = &fields[*iter_output];
+               struct ustctl_type *ut = &uf->type;
+
+               if (field_name) {
+                       strncpy(uf->name, field_name, LTTNG_UST_SYM_NAME_LEN);
+                       uf->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               } else {
+                       uf->name[0] = '\0';
+               }
+               strncpy(ut->u.enum_nestable.name, lt->u.enum_nestable.desc->name,
+                               LTTNG_UST_SYM_NAME_LEN);
+               ut->u.enum_nestable.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               ut->atype = ustctl_atype_enum_nestable;
+               (*iter_output)++;
+
+               ret = serialize_one_type(session, fields, iter_output, NULL,
+                               lt->u.enum_nestable.container_type);
+               if (ret)
+                       return -EINVAL;
+               if (session) {
+                       const struct lttng_enum *_enum;
+
+                       _enum = lttng_ust_enum_get_from_desc(session, lt->u.enum_nestable.desc);
+                       if (!_enum)
+                               return -EINVAL;
+                       ut->u.enum_nestable.id = _enum->id;
+               } else {
+                       ut->u.enum_nestable.id = -1ULL;
+               }
                break;
        }
        default:
@@ -1096,8 +1365,38 @@ int serialize_one_field(struct lttng_session *session,
        return 0;
 }
 
+static
+int serialize_one_field(struct lttng_session *session,
+               struct ustctl_field *fields, size_t *iter_output,
+               const struct lttng_event_field *lf)
+{
+       /* skip 'nowrite' fields */
+       if (lf->nowrite)
+               return 0;
+
+       return serialize_one_type(session, fields, iter_output, lf->name, &lf->type);
+}
+
 static
 int serialize_fields(struct lttng_session *session,
+               struct ustctl_field *ustctl_fields,
+               size_t *iter_output, size_t nr_lttng_fields,
+               const struct lttng_event_field *lttng_fields)
+{
+       int ret;
+       size_t i;
+
+       for (i = 0; i < nr_lttng_fields; i++) {
+               ret = serialize_one_field(session, ustctl_fields,
+                               iter_output, &lttng_fields[i]);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+static
+int alloc_serialize_fields(struct lttng_session *session,
                size_t *_nr_write_fields,
                struct ustctl_field **ustctl_fields,
                size_t nr_fields,
@@ -1105,7 +1404,7 @@ int serialize_fields(struct lttng_session *session,
 {
        struct ustctl_field *fields;
        int ret;
-       size_t i, iter_output = 0;
+       size_t iter_output = 0;
        ssize_t nr_write_fields;
 
        nr_write_fields = count_fields_recursive(nr_fields, lttng_fields);
@@ -1117,12 +1416,10 @@ int serialize_fields(struct lttng_session *session,
        if (!fields)
                return -ENOMEM;
 
-       for (i = 0; i < nr_fields; i++) {
-               ret = serialize_one_field(session, fields, &iter_output,
-                               &lttng_fields[i]);
-               if (ret)
-                       goto error_type;
-       }
+       ret = serialize_fields(session, fields, &iter_output, nr_fields,
+                       lttng_fields);
+       if (ret)
+               goto error_type;
 
        *_nr_write_fields = nr_write_fields;
        *ustctl_fields = fields;
@@ -1247,7 +1544,7 @@ int ustcomm_register_event(int sock,
 
        /* Calculate fields len, serialize fields. */
        if (nr_fields > 0) {
-               ret = serialize_fields(session, &nr_write_fields, &fields,
+               ret = alloc_serialize_fields(session, &nr_write_fields, &fields,
                                nr_fields, lttng_fields);
                if (ret)
                        return ret;
This page took 0.032136 seconds and 4 git commands to generate.