+ ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+ if (ret < 0) {
+ goto end;
+ }
+
+ ret = 0;
+end:
+ return ret;
+}
+
+int lttng_register_trigger(struct lttng_trigger *trigger)
+{
+ int ret;
+ struct lttcomm_session_msg lsm = {
+ .cmd_type = LTTNG_REGISTER_TRIGGER,
+ };
+ struct lttcomm_session_msg *message_lsm;
+ struct lttng_payload message;
+ struct lttng_payload reply;
+ struct lttng_trigger *reply_trigger = NULL;
+ enum lttng_domain_type domain_type;
+ const struct lttng_credentials user_creds = {
+ .uid = LTTNG_OPTIONAL_INIT_VALUE(geteuid()),
+ .gid = LTTNG_OPTIONAL_INIT_UNSET,
+ };
+
+
+ lttng_payload_init(&message);
+ lttng_payload_init(&reply);
+
+ if (!trigger) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (!trigger->creds.uid.is_set) {
+ /* Use the client's credentials as the trigger credentials. */
+ lttng_trigger_set_credentials(trigger, &user_creds);
+ } else {
+ /*
+ * Validate that either the current trigger credentials and the
+ * client credentials are identical or that the current user is
+ * root. The root user can register, unregister triggers for
+ * himself and other users.
+ *
+ * This check is also present on the sessiond side, using the
+ * credentials passed on the socket. These check are all
+ * "safety" checks.
+ */
+ const struct lttng_credentials *trigger_creds =
+ lttng_trigger_get_credentials(trigger);
+
+ if (!lttng_credentials_is_equal_uid(trigger_creds, &user_creds)) {
+ if (lttng_credentials_get_uid(&user_creds) != 0) {
+ ret = -LTTNG_ERR_EPERM;
+ goto end;
+ }
+ }
+ }
+
+ if (!lttng_trigger_validate(trigger)) {
+ ret = -LTTNG_ERR_INVALID_TRIGGER;
+ goto end;
+ }
+
+ domain_type = lttng_trigger_get_underlying_domain_type_restriction(
+ trigger);
+
+ lsm.domain.type = domain_type;
+
+ ret = lttng_dynamic_buffer_append(&message.buffer, &lsm, sizeof(lsm));
+ if (ret) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ ret = lttng_trigger_serialize(trigger, &message);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ /*
+ * This is needed to populate the trigger object size for the command
+ * header.
+ */
+ message_lsm = (struct lttcomm_session_msg *) message.buffer.data;
+
+ message_lsm->u.trigger.length = (uint32_t) message.buffer.size - sizeof(lsm);
+
+ {
+ struct lttng_payload_view message_view =
+ lttng_payload_view_from_payload(
+ &message, 0, -1);
+
+ message_lsm->fd_count = lttng_payload_view_get_fd_handle_count(
+ &message_view);
+ ret = lttng_ctl_ask_sessiond_payload(&message_view, &reply);
+ if (ret < 0) {