blob: fb6cf1e620a1abdf6dc71a52ae866782116948e1 [file] [log] [blame]
Brian Waters13d96012017-12-08 16:53:31 -06001/*********************************************************************************************************
2* Software License Agreement (BSD License) *
3* Author: Sebastien Decugis <sdecugis@freediameter.net> *
4* *
5* Copyright (c) 2013, WIDE Project and NICT *
6* All rights reserved. *
7* *
8* Redistribution and use of this software in source and binary forms, with or without modification, are *
9* permitted provided that the following conditions are met: *
10* *
11* * Redistributions of source code must retain the above *
12* copyright notice, this list of conditions and the *
13* following disclaimer. *
14* *
15* * Redistributions in binary form must reproduce the above *
16* copyright notice, this list of conditions and the *
17* following disclaimer in the documentation and/or other *
18* materials provided with the distribution. *
19* *
20* * Neither the name of the WIDE Project or NICT nor the *
21* names of its contributors may be used to endorse or *
22* promote products derived from this software without *
23* specific prior written permission of WIDE Project and *
24* NICT. *
25* *
26* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
27* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
28* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
29* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
30* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *
31* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
32* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF *
33* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
34*********************************************************************************************************/
35
36#include "fdcore-internal.h"
37#include "cnxctx.h"
38
39#include <netinet/tcp.h>
40#include <netinet/ip6.h>
41#include <sys/socket.h>
42
43/* Set the socket options for TCP sockets, before bind is called */
44static int fd_tcp_setsockopt(int family, int sk)
45{
46 int ret = 0;
47 int opt;
48
49 /* Clear the NODELAY option in case it was set, as requested by rfc3539#section-3.2 */
50 /* Note that this is supposed to be the default, so we could probably remove this call ... */
51 opt = 0;
52 ret = setsockopt(sk, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
53 if (ret != 0) {
54 ret = errno;
55 TRACE_DEBUG(INFO, "Unable to set the socket TCP_NODELAY option: %s", strerror(ret));
56 return ret;
57 }
58
59 /* Under Linux, we may also set the TCP_CONGESTION option to one of the following strings:
60 - reno (default)
61 - bic
62 - cubic
63 - highspeed
64 - htcp
65 - hybla
66 - illinois
67 - lp
68 - scalable
69 - vegas
70 - veno
71 - westwood
72 - yeah
73 */
74
75 /* In case of v6 address, force the v6only option, we use a different socket for v4 */
76 #ifdef IPV6_V6ONLY
77 if (family == AF_INET6) {
78 opt = 1;
79 CHECK_SYS(setsockopt(sk, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)));
80 }
81 #endif /* IPV6_V6ONLY */
82
83 {
84 opt = 1;
85 CHECK_SYS( setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) );
86 }
87
88 /* There are also others sockopt that can be set, but nothing useful for us AFAICT */
89
90 return 0;
91}
92
93/* Create a socket server and bind it */
94int fd_tcp_create_bind_server( int * sock, sSA * sa, socklen_t salen )
95{
96 TRACE_ENTRY("%p %p %d", sock, sa, salen);
97
98 CHECK_PARAMS( sock && sa );
99
100 /* Create the socket */
101 CHECK_SYS( *sock = socket(sa->sa_family, SOCK_STREAM, IPPROTO_TCP) );
102
103 /* Set the socket options */
104 CHECK_FCT( fd_tcp_setsockopt(sa->sa_family, *sock) );
105
106 /* Bind the socket */
107 CHECK_SYS( bind( *sock, sa, salen ) );
108
109 /* We're done */
110 return 0;
111}
112
113/* Allow clients connections on server sockets */
114int fd_tcp_listen( int sock )
115{
116 TRACE_ENTRY("%d", sock);
117 CHECK_SYS( listen(sock, 5) );
118 return 0;
119}
120
121/* Create a client socket and connect to remote server */
122int fd_tcp_client( int *sock, sSA * sa, socklen_t salen )
123{
124 int ret = 0;
125 int s;
126
127 TRACE_ENTRY("%p %p %d", sock, sa, salen);
128 CHECK_PARAMS( sock && (*sock <= 0) && sa && salen );
129
130 /* Create the socket */
131 CHECK_SYS( s = socket(sa->sa_family, SOCK_STREAM, IPPROTO_TCP) );
132
133 /* Set the socket options */
134 CHECK_FCT( fd_tcp_setsockopt(sa->sa_family, s) );
135
136 /* Cleanup if we are cancelled */
137 pthread_cleanup_push(fd_cleanup_socket, &s);
138
139 /* Try connecting to the remote address */
140 ret = connect(s, sa, salen);
141
142 pthread_cleanup_pop(0);
143
144 if (ret < 0) {
145 ret = errno;
146 LOG_A( "connect returned an error: %s", strerror(ret));
147 CHECK_SYS_DO( close(s), /* continue */ );
148 *sock = -1;
149 return ret;
150 }
151
152 /* Done! */
153 *sock = s;
154 return ret;
155}
156
157/* Get the remote name of a TCP socket */
158int fd_tcp_get_remote_ep(int sock, sSS * ss, socklen_t *sl)
159{
160 TRACE_ENTRY("%d %p %p", sock, ss, sl);
161 CHECK_PARAMS( ss && sl );
162
163 *sl = sizeof(sSS);
164 CHECK_SYS(getpeername(sock, (sSA *)ss, sl));
165
166 return 0;
167}
168