2 * Copyright (C) 2012 - David Goulet <dgoulet@efficios.com>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
8 * This program 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 General Public License for
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include <sys/types.h>
29 #include <common/defaults.h>
30 #include <common/error.h>
35 * INET protocol operations.
37 static const struct lttcomm_proto_ops inet6_ops
= {
38 .bind
= lttcomm_bind_inet6_sock
,
39 .close
= lttcomm_close_inet6_sock
,
40 .connect
= lttcomm_connect_inet6_sock
,
41 .accept
= lttcomm_accept_inet6_sock
,
42 .listen
= lttcomm_listen_inet6_sock
,
43 .recvmsg
= lttcomm_recvmsg_inet6_sock
,
44 .sendmsg
= lttcomm_sendmsg_inet6_sock
,
48 * Creates an PF_INET socket.
50 __attribute__((visibility("hidden")))
51 int lttcomm_create_inet6_sock(struct lttcomm_sock
*sock
, int type
, int proto
)
55 /* Create server socket */
56 if ((sock
->fd
= socket(PF_INET6
, type
, proto
)) < 0) {
57 PERROR("socket inet6");
61 sock
->ops
= &inet6_ops
;
64 * Set socket option to reuse the address.
66 ret
= setsockopt(sock
->fd
, SOL_SOCKET
, SO_REUSEADDR
, &val
, sizeof(int));
68 PERROR("setsockopt inet6");
79 * Bind socket and return.
81 __attribute__((visibility("hidden")))
82 int lttcomm_bind_inet6_sock(struct lttcomm_sock
*sock
)
86 ret
= bind(sock
->fd
, &sock
->sockaddr
.addr
.sin6
,
87 sizeof(sock
->sockaddr
.addr
.sin6
));
96 * Connect PF_INET socket.
98 __attribute__((visibility("hidden")))
99 int lttcomm_connect_inet6_sock(struct lttcomm_sock
*sock
)
103 ret
= connect(sock
->fd
, (struct sockaddr
*) &sock
->sockaddr
.addr
.sin6
,
104 sizeof(sock
->sockaddr
.addr
.sin6
));
107 * Don't print message on connect error, because connect is used in
108 * normal execution to detect if sessiond is alive.
116 closeret
= close(sock
->fd
);
118 PERROR("close inet6");
125 * Do an accept(2) on the sock and return the new lttcomm socket. The socket
126 * MUST be bind(2) before.
128 __attribute__((visibility("hidden")))
129 struct lttcomm_sock
*lttcomm_accept_inet6_sock(struct lttcomm_sock
*sock
)
133 struct lttcomm_sock
*new_sock
;
135 if (sock
->proto
== LTTCOMM_SOCK_UDP
) {
137 * accept(2) does not exist for UDP so simply return the passed socket.
143 new_sock
= lttcomm_alloc_sock(sock
->proto
);
144 if (new_sock
== NULL
) {
148 len
= sizeof(new_sock
->sockaddr
.addr
.sin6
);
151 new_fd
= accept(sock
->fd
,
152 (struct sockaddr
*) &new_sock
->sockaddr
.addr
.sin6
, &len
);
154 PERROR("accept inet6");
158 new_sock
->fd
= new_fd
;
159 new_sock
->ops
= &inet6_ops
;
170 * Make the socket listen using LTTNG_SESSIOND_COMM_MAX_LISTEN.
172 __attribute__((visibility("hidden")))
173 int lttcomm_listen_inet6_sock(struct lttcomm_sock
*sock
, int backlog
)
177 if (sock
->proto
== LTTCOMM_SOCK_UDP
) {
178 /* listen(2) does not exist for UDP so simply return success. */
183 /* Default listen backlog */
185 backlog
= LTTNG_SESSIOND_COMM_MAX_LISTEN
;
188 ret
= listen(sock
->fd
, backlog
);
190 PERROR("listen inet6");
198 * Receive data of size len in put that data into the buf param. Using recvmsg
201 * Return the size of received data.
203 __attribute__((visibility("hidden")))
204 ssize_t
lttcomm_recvmsg_inet6_sock(struct lttcomm_sock
*sock
, void *buf
,
205 size_t len
, int flags
)
212 memset(&msg
, 0, sizeof(msg
));
214 iov
[0].iov_base
= buf
;
215 iov
[0].iov_len
= len
;
219 msg
.msg_name
= (struct sockaddr
*) &sock
->sockaddr
.addr
.sin6
;
220 msg
.msg_namelen
= sizeof(sock
->sockaddr
.addr
.sin6
);
223 len_last
= iov
[0].iov_len
;
224 ret
= recvmsg(sock
->fd
, &msg
, flags
);
226 iov
[0].iov_base
+= ret
;
227 iov
[0].iov_len
-= ret
;
228 assert(ret
<= len_last
);
230 } while ((ret
> 0 && ret
< len_last
) || (ret
< 0 && errno
== EINTR
));
232 PERROR("recvmsg inet");
233 } else if (ret
> 0) {
236 /* Else ret = 0 meaning an orderly shutdown. */
242 * Send buf data of size len. Using sendmsg API.
244 * Return the size of sent data.
246 __attribute__((visibility("hidden")))
247 ssize_t
lttcomm_sendmsg_inet6_sock(struct lttcomm_sock
*sock
, void *buf
,
248 size_t len
, int flags
)
254 memset(&msg
, 0, sizeof(msg
));
256 iov
[0].iov_base
= buf
;
257 iov
[0].iov_len
= len
;
261 switch (sock
->proto
) {
262 case LTTCOMM_SOCK_UDP
:
263 msg
.msg_name
= (struct sockaddr
*) &sock
->sockaddr
.addr
.sin6
;
264 msg
.msg_namelen
= sizeof(sock
->sockaddr
.addr
.sin6
);
271 ret
= sendmsg(sock
->fd
, &msg
, flags
);
272 } while (ret
< 0 && errno
== EINTR
);
275 * Only warn about EPIPE when quiet mode is deactivated.
276 * We consider EPIPE as expected.
278 if (errno
!= EPIPE
|| !lttng_opt_quiet
) {
279 PERROR("sendmsg inet6");
287 * Shutdown cleanly and close.
289 __attribute__((visibility("hidden")))
290 int lttcomm_close_inet6_sock(struct lttcomm_sock
*sock
)
294 /* Don't try to close an invalid marked socket */
295 if (sock
->fd
== -1) {
299 ret
= close(sock
->fd
);
301 PERROR("close inet6");