2 * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 #include <lttng/notification/notification-internal.h>
19 #include <lttng/notification/channel-internal.h>
20 #include <lttng/condition/condition-internal.h>
21 #include <lttng/endpoint.h>
22 #include <common/error.h>
23 #include <common/utils.h>
24 #include <common/defaults.h>
26 #include "lttng-ctl-helper.h"
28 struct lttng_notification_channel
*lttng_notification_channel_create(
29 struct lttng_endpoint
*endpoint
)
32 bool is_in_tracing_group
= false, is_root
= false;
33 char *sock_path
= NULL
;
34 struct lttng_notification_channel
*channel
= NULL
;
37 endpoint
!= lttng_session_daemon_notification_endpoint
) {
41 sock_path
= zmalloc(LTTNG_PATH_MAX
);
46 channel
= zmalloc(sizeof(struct lttng_notification_channel
));
52 is_root
= (getuid() == 0);
54 is_in_tracing_group
= lttng_check_tracing_group();
57 if (is_root
|| is_in_tracing_group
) {
58 lttng_ctl_copy_string(sock_path
,
59 DEFAULT_GLOBAL_NOTIFICATION_CHANNEL_UNIX_SOCK
,
61 ret
= lttcomm_connect_unix_sock(sock_path
);
68 /* Fallback to local session daemon. */
69 ret
= snprintf(sock_path
, LTTNG_PATH_MAX
,
70 DEFAULT_HOME_NOTIFICATION_CHANNEL_UNIX_SOCK
,
71 utils_get_home_dir());
72 if (ret
< 0 || ret
>= LTTNG_PATH_MAX
) {
76 ret
= lttcomm_connect_unix_sock(sock_path
);
85 /* FIXME send creds */
90 lttng_notification_channel_destroy(channel
);
95 enum lttng_notification_channel_status
96 lttng_notification_channel_get_next_notification(
97 struct lttng_notification_channel
*channel
,
98 struct lttng_notification
**_notification
)
101 char *notification_buffer
= NULL
;
102 struct lttng_notification_comm comm
;
103 struct lttng_notification
*notification
= NULL
;
104 enum lttng_notification_channel_status status
=
105 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
;
107 if (!channel
|| !_notification
) {
108 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
;
112 ret
= lttcomm_recv_unix_sock(channel
->socket
, &comm
, sizeof(comm
));
113 if (ret
< sizeof(comm
)) {
114 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
118 notification_buffer
= zmalloc(comm
.length
+ sizeof(comm
));
119 if (!notification_buffer
) {
123 memcpy(notification_buffer
, &comm
, sizeof(comm
));
124 ret
= lttcomm_recv_unix_sock(channel
->socket
,
125 notification_buffer
+ sizeof(comm
),
127 if (ret
< (ssize_t
) comm
.length
) {
128 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
132 ret
= lttng_notification_create_from_buffer(notification_buffer
,
134 if (ret
!= (sizeof(comm
) + (ssize_t
) comm
.length
)) {
135 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
138 *_notification
= notification
;
140 free(notification_buffer
);
143 lttng_notification_destroy(notification
);
148 enum lttng_notification_channel_status
send_command(
149 struct lttng_notification_channel
*channel
,
150 enum lttng_notification_channel_command_type type
,
151 struct lttng_condition
*condition
)
154 ssize_t command_size
, ret
;
156 enum lttng_notification_channel_status status
=
157 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
;
158 char *command_buffer
= NULL
;
159 struct lttng_notification_channel_command cmd
= {
162 struct lttng_notification_channel_command_reply reply
;
165 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
;
169 socket
= channel
->socket
;
170 if (!lttng_condition_validate(condition
)) {
171 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
;
175 ret
= lttng_condition_serialize(condition
, NULL
);
177 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
;
180 assert(ret
< UINT32_MAX
);
181 cmd
.size
= (uint32_t) ret
;
182 command_size
= ret
+ sizeof(
183 struct lttng_notification_channel_command
);
184 command_buffer
= zmalloc(command_size
);
185 if (!command_buffer
) {
189 memcpy(command_buffer
, &cmd
, sizeof(cmd
));
190 ret
= lttng_condition_serialize(condition
,
191 command_buffer
+ sizeof(cmd
));
196 ret
= lttcomm_send_unix_sock(socket
, command_buffer
, command_size
);
198 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
202 /* Receive command reply. */
205 ret
= lttcomm_recv_unix_sock(socket
,
206 ((char *) &reply
) + received
,
207 sizeof(reply
) - received
);
209 status
= LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR
;
213 } while (received
< sizeof(reply
));
214 status
= (enum lttng_notification_channel_status
) reply
.status
;
216 free(command_buffer
);
220 enum lttng_notification_channel_status
lttng_notification_channel_subscribe(
221 struct lttng_notification_channel
*channel
,
222 struct lttng_condition
*condition
)
224 return send_command(channel
,
225 LTTNG_NOTIFICATION_CHANNEL_COMMAND_TYPE_SUBSCRIBE
,
229 enum lttng_notification_channel_status
lttng_notification_channel_unsubscribe(
230 struct lttng_notification_channel
*channel
,
231 struct lttng_condition
*condition
)
233 return send_command(channel
,
234 LTTNG_NOTIFICATION_CHANNEL_COMMAND_TYPE_UNSUBSCRIBE
,
238 void lttng_notification_channel_destroy(
239 struct lttng_notification_channel
*channel
)
245 if (channel
->socket
>= 0) {
246 (void) lttcomm_close_unix_sock(channel
->socket
);