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>
30 #include <common/common.h>
35 * INET protocol operations.
37 static const struct lttcomm_proto_ops inet_ops
= {
38 .bind
= lttcomm_bind_inet_sock
,
39 .close
= lttcomm_close_inet_sock
,
40 .connect
= lttcomm_connect_inet_sock
,
41 .accept
= lttcomm_accept_inet_sock
,
42 .listen
= lttcomm_listen_inet_sock
,
43 .recvmsg
= lttcomm_recvmsg_inet_sock
,
44 .sendmsg
= lttcomm_sendmsg_inet_sock
,
47 unsigned long lttcomm_inet_tcp_timeout
;
50 * Creates an PF_INET socket.
53 int lttcomm_create_inet_sock(struct lttcomm_sock
*sock
, int type
, int proto
)
57 /* Create server socket */
58 if ((sock
->fd
= socket(PF_INET
, type
, proto
)) < 0) {
59 PERROR("socket inet");
63 sock
->ops
= &inet_ops
;
66 * Set socket option to reuse the address.
68 ret
= setsockopt(sock
->fd
, SOL_SOCKET
, SO_REUSEADDR
, &val
, sizeof(int));
70 PERROR("setsockopt inet");
81 * Bind socket and return.
84 int lttcomm_bind_inet_sock(struct lttcomm_sock
*sock
)
88 ret
= bind(sock
->fd
, &sock
->sockaddr
.addr
.sin
,
89 sizeof(sock
->sockaddr
.addr
.sin
));
98 * Connect PF_INET socket.
101 int lttcomm_connect_inet_sock(struct lttcomm_sock
*sock
)
105 ret
= connect(sock
->fd
, (struct sockaddr
*) &sock
->sockaddr
.addr
.sin
,
106 sizeof(sock
->sockaddr
.addr
.sin
));
115 closeret
= close(sock
->fd
);
117 PERROR("close inet");
124 * Do an accept(2) on the sock and return the new lttcomm socket. The socket
125 * MUST be bind(2) before.
128 struct lttcomm_sock
*lttcomm_accept_inet_sock(struct lttcomm_sock
*sock
)
132 struct lttcomm_sock
*new_sock
;
134 if (sock
->proto
== LTTCOMM_SOCK_UDP
) {
136 * accept(2) does not exist for UDP so simply return the passed socket.
142 new_sock
= lttcomm_alloc_sock(sock
->proto
);
143 if (new_sock
== NULL
) {
147 len
= sizeof(new_sock
->sockaddr
.addr
.sin
);
150 new_fd
= accept(sock
->fd
, (struct sockaddr
*) &new_sock
->sockaddr
.addr
.sin
,
153 PERROR("accept inet");
157 new_sock
->fd
= new_fd
;
158 new_sock
->ops
= &inet_ops
;
169 * Make the socket listen using LTTNG_SESSIOND_COMM_MAX_LISTEN.
172 int lttcomm_listen_inet_sock(struct lttcomm_sock
*sock
, int backlog
)
176 if (sock
->proto
== LTTCOMM_SOCK_UDP
) {
177 /* listen(2) does not exist for UDP so simply return success. */
182 /* Default listen backlog */
184 backlog
= LTTNG_SESSIOND_COMM_MAX_LISTEN
;
187 ret
= listen(sock
->fd
, backlog
);
189 PERROR("listen inet");
197 * Receive data of size len in put that data into the buf param. Using recvmsg
200 * Return the size of received data.
203 ssize_t
lttcomm_recvmsg_inet_sock(struct lttcomm_sock
*sock
, void *buf
,
204 size_t len
, int flags
)
211 memset(&msg
, 0, sizeof(msg
));
213 iov
[0].iov_base
= buf
;
214 iov
[0].iov_len
= len
;
218 msg
.msg_name
= (struct sockaddr
*) &sock
->sockaddr
.addr
.sin
;
219 msg
.msg_namelen
= sizeof(sock
->sockaddr
.addr
.sin
);
222 len_last
= iov
[0].iov_len
;
223 ret
= recvmsg(sock
->fd
, &msg
, flags
);
225 iov
[0].iov_base
+= ret
;
226 iov
[0].iov_len
-= ret
;
227 assert(ret
<= len_last
);
229 } while ((ret
> 0 && ret
< len_last
) || (ret
< 0 && errno
== EINTR
));
231 PERROR("recvmsg inet");
232 } else if (ret
> 0) {
235 /* Else ret = 0 meaning an orderly shutdown. */
241 * Send buf data of size len. Using sendmsg API.
243 * Return the size of sent data.
246 ssize_t
lttcomm_sendmsg_inet_sock(struct lttcomm_sock
*sock
, void *buf
,
247 size_t len
, int flags
)
253 memset(&msg
, 0, sizeof(msg
));
255 iov
[0].iov_base
= buf
;
256 iov
[0].iov_len
= len
;
260 switch (sock
->proto
) {
261 case LTTCOMM_SOCK_UDP
:
262 msg
.msg_name
= (struct sockaddr
*) &sock
->sockaddr
.addr
.sin
;
263 msg
.msg_namelen
= sizeof(sock
->sockaddr
.addr
.sin
);
270 ret
= sendmsg(sock
->fd
, &msg
, flags
);
271 } while (ret
< 0 && errno
== EINTR
);
274 * Only warn about EPIPE when quiet mode is deactivated.
275 * We consider EPIPE as expected.
277 if (errno
!= EPIPE
|| !lttng_opt_quiet
) {
278 PERROR("sendmsg inet");
286 * Shutdown cleanly and close.
289 int lttcomm_close_inet_sock(struct lttcomm_sock
*sock
)
293 /* Don't try to close an invalid marked socket */
294 if (sock
->fd
== -1) {
298 ret
= close(sock
->fd
);
300 PERROR("close inet");
310 * Return value read from /proc or else 0 if value is not found.
312 static unsigned long read_proc_value(const char *path
)
316 unsigned long val
= 0;
319 fd
= open(path
, O_RDONLY
);
324 ret
= read(fd
, buf
, sizeof(buf
));
326 PERROR("read proc failed");
331 r_val
= strtol(buf
, NULL
, 10);
332 if (errno
!= 0 || r_val
< -1L) {
344 PERROR("close /proc value");
351 void lttcomm_inet_init(void)
353 unsigned long syn_retries
, fin_timeout
, syn_timeout
;
355 /* Assign default value and see if we can change it. */
356 lttcomm_inet_tcp_timeout
= DEFAULT_INET_TCP_TIMEOUT
;
358 syn_retries
= read_proc_value(LTTCOMM_INET_PROC_SYN_RETRIES_PATH
);
359 fin_timeout
= read_proc_value(LTTCOMM_INET_PROC_FIN_TIMEOUT_PATH
);
361 syn_timeout
= syn_retries
* LTTCOMM_INET_SYN_TIMEOUT_FACTOR
;
364 * Get the maximum between the two possible timeout value and use that to
365 * get the maximum with the default timeout.
367 lttcomm_inet_tcp_timeout
= max_t(unsigned long,
368 max_t(unsigned long, syn_timeout
, fin_timeout
),
369 lttcomm_inet_tcp_timeout
);
371 DBG("TCP inet operation timeout set to %lu sec", lttcomm_inet_tcp_timeout
);