/* * Returns 0 on success, negative UST or system error value on error. */ int ustctl_recv_register_channel(int sock, int *session_objd, /* session descriptor (output) */ int *channel_objd, /* channel descriptor (output) */ size_t *nr_fields, struct ustctl_field **fields) { ssize_t len; struct ustcomm_notify_channel_msg msg; size_t fields_len; struct ustctl_field *a_fields; len = ustcomm_recv_unix_sock(sock, &msg, sizeof(msg)); if (len > 0 && len != sizeof(msg)) return -EIO; if (len == 0) return -EPIPE; if (len < 0) return len; *session_objd = msg.session_objd; *channel_objd = msg.channel_objd; fields_len = msg.ctx_fields_len; if (fields_len % sizeof(*a_fields) != 0) { return -EINVAL; } /* recv fields */ if (fields_len) { a_fields = zmalloc(fields_len); if (!a_fields) { len = -ENOMEM; goto alloc_error; } len = ustcomm_recv_unix_sock(sock, a_fields, fields_len); if (len > 0 && len != fields_len) { len = -EIO; goto fields_error; } if (len == 0) { len = -EPIPE; goto fields_error; } if (len < 0) { goto fields_error; } *fields = a_fields; } else { *fields = NULL; } *nr_fields = fields_len / sizeof(*a_fields); return 0; fields_error: free(a_fields); alloc_error: return len; }
int ustctl_tracepoint_field_list_get(int sock, int tp_field_list_handle, struct lttng_ust_field_iter *iter) { struct ustcomm_ust_msg lum; struct ustcomm_ust_reply lur; int ret; ssize_t len; if (!iter) return -EINVAL; memset(&lum, 0, sizeof(lum)); lum.handle = tp_field_list_handle; lum.cmd = LTTNG_UST_TRACEPOINT_FIELD_LIST_GET; ret = ustcomm_send_app_cmd(sock, &lum, &lur); if (ret) return ret; len = ustcomm_recv_unix_sock(sock, iter, sizeof(*iter)); if (len != sizeof(*iter)) { return -EINVAL; } DBG("received tracepoint field list entry event_name %s event_loglevel %d field_name %s field_type %d", iter->event_name, iter->loglevel, iter->field_name, iter->type); return 0; }
int ustctl_recv_notify(int sock, enum ustctl_notify_cmd *notify_cmd) { struct ustcomm_notify_hdr header; ssize_t len; len = ustcomm_recv_unix_sock(sock, &header, sizeof(header)); if (len > 0 && len != sizeof(header)) return -EIO; if (len == 0) return -EPIPE; if (len < 0) return len; switch (header.notify_cmd) { case 0: *notify_cmd = USTCTL_NOTIFY_CMD_EVENT; break; case 1: *notify_cmd = USTCTL_NOTIFY_CMD_CHANNEL; break; default: return -EINVAL; } return 0; }
int main(int argc, char **argv) { const char *home_dir; char home_rundir[PATH_MAX]; char *cmd = NULL; int ret, wait_shm_fd; struct sigaction act; mode_t old_umask = 0; long page_size; set_ulimit(); /* Ignore sigpipe */ memset(&act, 0, sizeof(act)); ret = sigemptyset(&act.sa_mask); if (ret == -1) { perror("sigemptyset"); return -1; } act.sa_handler = SIG_IGN; ret = sigaction(SIGPIPE, &act, NULL); if (ret == -1) { perror("sigaction"); return -1; } /* Handle SIGTERM */ act.sa_handler = handle_signals; ret = sigaction(SIGTERM, &act, NULL); if (ret == -1) { perror("sigaction"); return -1; } /* Handle SIGINT */ ret = sigaction(SIGINT, &act, NULL); if (ret == -1) { perror("sigaction"); return -1; } page_size = sysconf(_SC_PAGE_SIZE); if (page_size <= 0) { if (!page_size) { errno = EINVAL; } perror("Error in sysconf(_SC_PAGE_SIZE)"); return -1; } if (geteuid() == 0) { ret = mkdir(LTTNG_RUNDIR, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); if (ret && errno != EEXIST) { perror("mkdir"); return -1; } wait_shm_fd = get_wait_shm(DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH, page_size, 1); if (wait_shm_fd < 0) { perror("global wait shm error"); return -1; } strcpy(apps_sock_path, DEFAULT_GLOBAL_APPS_UNIX_SOCK); old_umask = umask(0); } else { home_dir = (const char *) getenv("HOME"); if (!home_dir) { perror("getenv error"); return -ENOENT; } snprintf(home_rundir, PATH_MAX, LTTNG_HOME_RUNDIR, home_dir); ret = mkdir(home_rundir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); if (ret && errno != EEXIST) { perror("mkdir"); return -1; } snprintf(local_apps_wait_shm_path, PATH_MAX, DEFAULT_HOME_APPS_WAIT_SHM_PATH, getuid()); wait_shm_fd = get_wait_shm(local_apps_wait_shm_path, page_size, 0); if (wait_shm_fd < 0) { perror("local wait shm error"); return -1; } snprintf(apps_sock_path, PATH_MAX, DEFAULT_HOME_APPS_UNIX_SOCK, home_dir); } ret = ustcomm_create_unix_sock(apps_sock_path); if (ret < 0) { perror("create error"); return ret; } apps_socket = ret; if (getuid() == 0) { /* File permission MUST be 666 */ ret = chmod(apps_sock_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (ret < 0) { printf("Set file permissions failed: %s\n", apps_sock_path); perror("chmod"); goto end; } umask(old_umask); } ret = ustcomm_listen_unix_sock(apps_socket); if (ret < 0) { perror("listen error"); return ret; } /* wake up futexes */ ret = update_futex(wait_shm_fd, 1); if (ret) { fprintf(stderr, "Error wakeup futex\n"); return -1; } for (;;) { int sock; ssize_t len; struct { uint32_t major; uint32_t minor; pid_t pid; pid_t ppid; uid_t uid; gid_t gid; uint32_t bits_per_long; char name[16]; /* Process name */ } reg_msg; char bufname[17]; if (quit_program) break; printf("Accepting application registration\n"); sock = ustcomm_accept_unix_sock(apps_socket); if (sock < 0) { perror("accept error"); goto end; } /* * Basic recv here to handle the very simple data * that the libust send to register (reg_msg). */ len = ustcomm_recv_unix_sock(sock, ®_msg, sizeof(reg_msg)); if (len < 0 || len != sizeof(reg_msg)) { perror("ustcomm_recv_unix_sock"); continue; } memcpy(bufname, reg_msg.name, 16); bufname[16] = '\0'; printf("Application %s pid %u ppid %u uid %u gid %u has registered (version : %u.%u)\n", bufname, reg_msg.pid, reg_msg.ppid, reg_msg.uid, reg_msg.gid, reg_msg.major, reg_msg.minor); ret = send_app_msgs(sock); if (ret) { printf("Error in send_app_msgs.\n"); sleep(1); } close(sock); } end: printf("quitting.\n"); /* Let applications know we are not responding anymore */ ret = update_futex(wait_shm_fd, 0); if (ret) { fprintf(stderr, "Error wakeup futex\n"); return -1; } if (geteuid()) { printf("Removing %s directory\n", home_rundir); ret = asprintf(&cmd, "rm -rf %s", home_rundir); if (ret < 0) { printf("asprintf failed. Something is really wrong!\n"); return -1; } /* Remove lttng run directory */ ret = system(cmd); if (ret < 0) { printf("Unable to clean %s\n", home_rundir); return -1; } } return 0; }
int ustctl_recv_stream_from_consumer(int sock, struct lttng_ust_object_data **_stream_data) { struct lttng_ust_object_data *stream_data; ssize_t len; int ret; int fds[2]; stream_data = zmalloc(sizeof(*stream_data)); if (!stream_data) { ret = -ENOMEM; goto error_alloc; } stream_data->type = LTTNG_UST_OBJECT_TYPE_STREAM; stream_data->handle = -1; /* recv mmap size */ len = ustcomm_recv_unix_sock(sock, &stream_data->size, sizeof(stream_data->size)); if (len != sizeof(stream_data->size)) { if (len < 0) ret = len; else ret = -EINVAL; goto error; } if (stream_data->size == -1) { ret = -LTTNG_UST_ERR_NOENT; goto error; } /* recv stream nr */ len = ustcomm_recv_unix_sock(sock, &stream_data->u.stream.stream_nr, sizeof(stream_data->u.stream.stream_nr)); if (len != sizeof(stream_data->u.stream.stream_nr)) { if (len < 0) ret = len; else ret = -EINVAL; goto error; } /* recv shm fd and wakeup fd */ len = ustcomm_recv_fds_unix_sock(sock, fds, 2); if (len <= 0) { if (len < 0) { ret = len; goto error; } else { ret = -EIO; goto error; } } stream_data->u.stream.shm_fd = fds[0]; stream_data->u.stream.wakeup_fd = fds[1]; *_stream_data = stream_data; return 0; error: free(stream_data); error_alloc: return ret; }
int ustctl_recv_channel_from_consumer(int sock, struct lttng_ust_object_data **_channel_data) { struct lttng_ust_object_data *channel_data; ssize_t len; int wakeup_fd; int ret; channel_data = zmalloc(sizeof(*channel_data)); if (!channel_data) { ret = -ENOMEM; goto error_alloc; } channel_data->type = LTTNG_UST_OBJECT_TYPE_CHANNEL; channel_data->handle = -1; /* recv mmap size */ len = ustcomm_recv_unix_sock(sock, &channel_data->size, sizeof(channel_data->size)); if (len != sizeof(channel_data->size)) { if (len < 0) ret = len; else ret = -EINVAL; goto error; } /* recv channel type */ len = ustcomm_recv_unix_sock(sock, &channel_data->u.channel.type, sizeof(channel_data->u.channel.type)); if (len != sizeof(channel_data->u.channel.type)) { if (len < 0) ret = len; else ret = -EINVAL; goto error; } /* recv channel data */ channel_data->u.channel.data = zmalloc(channel_data->size); if (!channel_data->u.channel.data) { ret = -ENOMEM; goto error; } len = ustcomm_recv_unix_sock(sock, channel_data->u.channel.data, channel_data->size); if (len != channel_data->size) { if (len < 0) ret = len; else ret = -EINVAL; goto error_recv_data; } /* recv wakeup fd */ len = ustcomm_recv_fds_unix_sock(sock, &wakeup_fd, 1); if (len <= 0) { if (len < 0) { ret = len; goto error_recv_data; } else { ret = -EIO; goto error_recv_data; } } channel_data->u.channel.wakeup_fd = wakeup_fd; *_channel_data = channel_data; return 0; error_recv_data: free(channel_data->u.channel.data); error: free(channel_data); error_alloc: return ret; }
/* * Returns 0 on success, negative error value on error. */ int ustctl_recv_register_event(int sock, int *session_objd, int *channel_objd, char *event_name, int *loglevel, char **signature, size_t *nr_fields, struct ustctl_field **fields, char **model_emf_uri) { ssize_t len; struct ustcomm_notify_event_msg msg; size_t signature_len, fields_len, model_emf_uri_len; char *a_sign = NULL, *a_model_emf_uri = NULL; struct ustctl_field *a_fields = NULL; len = ustcomm_recv_unix_sock(sock, &msg, sizeof(msg)); if (len > 0 && len != sizeof(msg)) return -EIO; if (len == 0) return -EPIPE; if (len < 0) return len; *session_objd = msg.session_objd; *channel_objd = msg.channel_objd; strncpy(event_name, msg.event_name, LTTNG_UST_SYM_NAME_LEN); event_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; *loglevel = msg.loglevel; signature_len = msg.signature_len; fields_len = msg.fields_len; if (fields_len % sizeof(*a_fields) != 0) { return -EINVAL; } model_emf_uri_len = msg.model_emf_uri_len; /* recv signature. contains at least \0. */ a_sign = zmalloc(signature_len); if (!a_sign) return -ENOMEM; len = ustcomm_recv_unix_sock(sock, a_sign, signature_len); if (len > 0 && len != signature_len) { len = -EIO; goto signature_error; } if (len == 0) { len = -EPIPE; goto signature_error; } if (len < 0) { goto signature_error; } /* Enforce end of string */ a_sign[signature_len - 1] = '\0'; /* recv fields */ if (fields_len) { a_fields = zmalloc(fields_len); if (!a_fields) { len = -ENOMEM; goto signature_error; } len = ustcomm_recv_unix_sock(sock, a_fields, fields_len); if (len > 0 && len != fields_len) { len = -EIO; goto fields_error; } if (len == 0) { len = -EPIPE; goto fields_error; } if (len < 0) { goto fields_error; } } if (model_emf_uri_len) { /* recv model_emf_uri_len */ a_model_emf_uri = zmalloc(model_emf_uri_len); if (!a_model_emf_uri) { len = -ENOMEM; goto fields_error; } len = ustcomm_recv_unix_sock(sock, a_model_emf_uri, model_emf_uri_len); if (len > 0 && len != model_emf_uri_len) { len = -EIO; goto model_error; } if (len == 0) { len = -EPIPE; goto model_error; } if (len < 0) { goto model_error; } /* Enforce end of string */ a_model_emf_uri[model_emf_uri_len - 1] = '\0'; } *signature = a_sign; *nr_fields = fields_len / sizeof(*a_fields); *fields = a_fields; *model_emf_uri = a_model_emf_uri; return 0; model_error: free(a_model_emf_uri); fields_error: free(a_fields); signature_error: free(a_sign); return len; }
/* * Returns 0 on success, negative error value on error. */ int ustctl_recv_reg_msg(int sock, enum ustctl_socket_type *type, uint32_t *major, uint32_t *minor, uint32_t *pid, uint32_t *ppid, uint32_t *uid, uint32_t *gid, uint32_t *bits_per_long, uint32_t *uint8_t_alignment, uint32_t *uint16_t_alignment, uint32_t *uint32_t_alignment, uint32_t *uint64_t_alignment, uint32_t *long_alignment, int *byte_order, char *name) { ssize_t len; struct ustctl_reg_msg reg_msg; len = ustcomm_recv_unix_sock(sock, ®_msg, sizeof(reg_msg)); if (len > 0 && len != sizeof(reg_msg)) return -EIO; if (len == 0) return -EPIPE; if (len < 0) return len; if (reg_msg.magic == LTTNG_UST_COMM_MAGIC) { *byte_order = BYTE_ORDER == BIG_ENDIAN ? BIG_ENDIAN : LITTLE_ENDIAN; } else if (reg_msg.magic == bswap_32(LTTNG_UST_COMM_MAGIC)) { *byte_order = BYTE_ORDER == BIG_ENDIAN ? LITTLE_ENDIAN : BIG_ENDIAN; } else { return -LTTNG_UST_ERR_INVAL_MAGIC; } switch (reg_msg.socket_type) { case 0: *type = USTCTL_SOCKET_CMD; break; case 1: *type = USTCTL_SOCKET_NOTIFY; break; default: return -LTTNG_UST_ERR_INVAL_SOCKET_TYPE; } *major = reg_msg.major; *minor = reg_msg.minor; *pid = reg_msg.pid; *ppid = reg_msg.ppid; *uid = reg_msg.uid; *gid = reg_msg.gid; *bits_per_long = reg_msg.bits_per_long; *uint8_t_alignment = reg_msg.uint8_t_alignment; *uint16_t_alignment = reg_msg.uint16_t_alignment; *uint32_t_alignment = reg_msg.uint32_t_alignment; *uint64_t_alignment = reg_msg.uint64_t_alignment; *long_alignment = reg_msg.long_alignment; memcpy(name, reg_msg.name, LTTNG_UST_ABI_PROCNAME_LEN); if (reg_msg.major != LTTNG_UST_ABI_MAJOR_VERSION) { return -LTTNG_UST_ERR_UNSUP_MAJOR; } return 0; }