10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <netinet/in.h>
13 #include <netinet/tcp.h>
14 #ifdef HAVE_NETINET_TCP_FSM_H
15 #include <netinet/tcp_fsm.h>
17 #include <arpa/inet.h>
23 #ifdef HAVE_NETINET_TCP_FSM_H
25 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
26 # define __TCP_CLOSE TCPS_CLOSED
29 # define __TCP_ESTABLISHED TCP_ESTABLISHED
30 # define __TCP_CLOSE TCP_CLOSE
34 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
37 static int setup_echo_srv_tcp_ipv4(void **state)
39 torture_setup_echo_srv_tcp_ipv4(state);
45 static int setup_echo_srv_tcp_ipv6(void **state)
47 torture_setup_echo_srv_tcp_ipv6(state);
52 static int setup_ipv6(void **state)
54 torture_setup_socket_dir(state);
60 static int teardown(void **state)
62 torture_teardown_echo_srv(state);
67 static void test_sockopt_sndbuf(void **state)
69 struct torture_address addr = {
70 .sa_socklen = sizeof(struct sockaddr_in),
73 socklen_t olen = sizeof(obufsize);
75 socklen_t glen = sizeof(gbufsize);
80 (void) state; /* unused */
82 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
83 assert_int_not_equal(s, -1);
85 addr.sa.in.sin_family = AF_INET;
86 addr.sa.in.sin_port = htons(torture_server_port());
88 rc = inet_pton(addr.sa.in.sin_family,
89 torture_server_address(AF_INET),
90 &addr.sa.in.sin_addr);
91 assert_int_equal(rc, 1);
93 rc = connect(s, &addr.sa.s, addr.sa_socklen);
94 assert_int_equal(rc, 0);
96 rc = getsockopt(s, SOL_SOCKET, SO_SNDBUF, &obufsize, &olen);
97 assert_int_equal(rc, 0);
99 /* request 4k, on Linux the kernel doubles the value */
101 rc = setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sbufsize, sizeof(sbufsize));
102 assert_int_equal(rc, 0);
104 rc = getsockopt(s, SOL_SOCKET, SO_SNDBUF, &gbufsize, &glen);
105 assert_int_equal(rc, 0);
107 assert_true(sbufsize == gbufsize || sbufsize == gbufsize/2);
113 # ifdef SO_PROTOTYPE /* The Solaris name */
114 # define SO_PROTOCOL SO_PROTOTYPE
115 # endif /* SO_PROTOTYPE */
116 #endif /* SO_PROTOCOL */
118 static void test_sockopt_so(void **state)
120 struct torture_address addr = {
121 .sa_socklen = sizeof(struct sockaddr_in),
126 #endif /* SO_DOMAIN */
128 int so_protocol = -1;
130 #endif /* SO_PROTOCOL */
134 (void) state; /* unused */
136 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
137 assert_int_not_equal(s, -1);
139 addr.sa.in.sin_family = AF_INET;
140 addr.sa.in.sin_port = htons(torture_server_port());
142 rc = inet_pton(addr.sa.in.sin_family,
143 torture_server_address(AF_INET),
144 &addr.sa.in.sin_addr);
145 assert_int_equal(rc, 1);
147 rc = connect(s, &addr.sa.s, addr.sa_socklen);
148 assert_int_equal(rc, 0);
151 so_len = sizeof(so_domain);
157 assert_return_code(rc, errno);
158 assert_int_equal(so_domain, AF_INET);
159 assert_int_equal(so_len, sizeof(int));
160 #endif /* SO_DOMAIN */
163 so_len = sizeof(so_protocol);
169 assert_return_code(rc, errno);
170 assert_int_equal(so_protocol, IPPROTO_TCP);
171 assert_int_equal(so_len, sizeof(int));
173 so_len = sizeof(so_type);
179 assert_return_code(rc, errno);
180 assert_int_equal(so_type, SOCK_STREAM);
181 assert_int_equal(so_len, sizeof(int));
182 #endif /* SO_PROTOCOL */
188 static void test_sockopt_so6(void **state)
190 struct torture_address addr = {
191 .sa_socklen = sizeof(struct sockaddr_in),
195 #endif /* SO_DOMAIN */
198 int so_protocol = -1;
200 #endif /* SO_PROTOCOL */
204 (void) state; /* unused */
206 s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
207 assert_int_not_equal(s, -1);
209 addr.sa.in6.sin6_family = AF_INET6;
210 addr.sa.in6.sin6_port = htons(torture_server_port());
212 rc = inet_pton(addr.sa.in6.sin6_family,
213 torture_server_address(AF_INET6),
214 &addr.sa.in6.sin6_addr);
215 assert_int_equal(rc, 1);
217 rc = connect(s, &addr.sa.s, addr.sa_socklen);
218 assert_int_equal(rc, 0);
221 so_len = sizeof(so_domain);
227 assert_return_code(rc, errno);
228 assert_int_equal(so_domain, AF_INET6);
229 assert_int_equal(so_len, sizeof(int));
230 #endif /* SO_DOMAIN */
233 so_len = sizeof(so_protocol);
239 assert_return_code(rc, errno);
240 assert_int_equal(so_protocol, IPPROTO_TCP);
241 assert_int_equal(so_len, sizeof(int));
243 so_len = sizeof(so_type);
249 assert_return_code(rc, errno);
250 assert_int_equal(so_type, SOCK_STREAM);
251 assert_int_equal(so_len, sizeof(int));
252 #endif /* SO_PROTOCOL */
257 static void test_bind_ipv6_only(void **state)
259 struct addrinfo hints;
260 struct addrinfo *res, *ri;
265 (void) state; /* unused */
268 hints.ai_family = AF_UNSPEC;
269 hints.ai_socktype = SOCK_STREAM;
270 hints.ai_flags = AI_PASSIVE;
272 rc = getaddrinfo(torture_server_address(AF_INET6), svc, &hints, &res);
273 assert_int_equal(rc, 0);
275 for (ri = res; ri != NULL; ri = ri->ai_next) {
278 s = socket(ri->ai_family,
281 assert_int_not_equal(rc, -1);
288 switch(ri->ai_family) {
290 assert_int_equal(rc, -1);
294 assert_int_equal(rc, 0);
296 rc = bind(s, ri->ai_addr, ri->ai_addrlen);
297 assert_int_equal(rc, 0);
310 static void test_sockopt_tcp(void **state)
312 struct torture_address addr = {
313 .sa_socklen = sizeof(struct sockaddr_in),
317 struct tcp_info info;
319 socklen_t optlen = sizeof(int);
324 (void) state; /* unused */
326 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
327 assert_int_not_equal(s, -1);
329 addr.sa.in.sin_family = AF_INET;
330 addr.sa.in.sin_port = htons(torture_server_port());
332 rc = inet_pton(addr.sa.in.sin_family,
333 torture_server_address(AF_INET),
334 &addr.sa.in.sin_addr);
335 assert_int_equal(rc, 1);
339 optlen = sizeof(info);
340 rc = getsockopt(s, IPPROTO_TCP, TCP_INFO, &info, &optlen);
341 assert_return_code(rc, errno);
342 assert_int_equal(optlen, sizeof(info));
343 printf("info.tcpi_state=0x%x\n", info.tcpi_state);
344 printf("info.tcpi_rto=%u\n", info.tcpi_rto);
345 printf("info.tcpi_rtt=%u\n", info.tcpi_rtt);
346 printf("info.tcpi_rttvar=%u\n", info.tcpi_rttvar);
347 assert_int_equal(info.tcpi_state, __TCP_CLOSE);
348 assert_int_not_equal(info.tcpi_rto, 0);
349 assert_int_equal(info.tcpi_rtt, 0);
350 assert_int_not_equal(info.tcpi_rttvar, 0);
351 #endif /* TCP_INFO */
353 rc = connect(s, &addr.sa.s, addr.sa_socklen);
354 assert_int_equal(rc, 0);
357 optlen = sizeof(int);
358 rc = getsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen);
359 assert_return_code(rc, errno);
360 assert_int_equal(opt, 0);
362 opt = 1; /* Turn on TCP_NODELAY */
363 optlen = sizeof(int);
364 rc = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, optlen);
365 assert_return_code(rc, errno);
368 optlen = sizeof(int);
369 rc = getsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen);
370 assert_return_code(rc, errno);
371 assert_int_equal(opt, 1);
375 optlen = sizeof(info);
376 rc = getsockopt(s, IPPROTO_TCP, TCP_INFO, &info, &optlen);
377 assert_return_code(rc, errno);
378 assert_int_equal(optlen, sizeof(info));
379 printf("info.tcpi_state=0x%x\n", info.tcpi_state);
380 printf("info.tcpi_rto=%u\n", info.tcpi_rto);
381 printf("info.tcpi_rtt=%u\n", info.tcpi_rtt);
382 printf("info.tcpi_rttvar=%u\n", info.tcpi_rttvar);
383 assert_int_equal(info.tcpi_state, __TCP_ESTABLISHED);
384 assert_int_not_equal(info.tcpi_rto, 0);
385 assert_int_not_equal(info.tcpi_rtt, 0);
386 assert_int_not_equal(info.tcpi_rttvar, 0);
387 #endif /* TCP_INFO */
395 const struct CMUnitTest sockopt_tests[] = {
396 cmocka_unit_test_setup_teardown(test_sockopt_sndbuf,
397 setup_echo_srv_tcp_ipv4,
399 cmocka_unit_test_setup_teardown(test_sockopt_so,
400 setup_echo_srv_tcp_ipv4,
403 cmocka_unit_test_setup_teardown(test_sockopt_so6,
404 setup_echo_srv_tcp_ipv6,
406 cmocka_unit_test_setup_teardown(test_bind_ipv6_only,
410 cmocka_unit_test_setup_teardown(test_sockopt_tcp,
411 setup_echo_srv_tcp_ipv4,
415 rc = cmocka_run_group_tests(sockopt_tests, NULL, NULL);