test_echo_tcp_socket_options.c: add tests for TCP_INFO
authorStefan Metzmacher <metze@samba.org>
Fri, 19 Jun 2020 18:52:23 +0000 (20:52 +0200)
committerStefan Metzmacher <metze@samba.org>
Fri, 19 Jun 2020 20:59:00 +0000 (22:59 +0200)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
tests/echo_srv.c
tests/test_echo_tcp_socket_options.c

index 93778f21f66ffd3e450df773eb093676787f4ca9..87c85f74b22a96ca54878de502b98c3d5e123141 100644 (file)
@@ -9,6 +9,10 @@
 
 #include <arpa/inet.h>
 #include <netinet/in.h>
+#include <netinet/tcp.h>
+#ifdef HAVE_NETINET_TCP_FSM_H
+#include <netinet/tcp_fsm.h>
+#endif
 #include <netdb.h>
 #include <resolv.h>
 
@@ -315,6 +319,34 @@ static int setup_srv(struct echo_srv_opts *opts, int *_sock)
             perror("listen");
             return ret;
         }
+#ifdef TCP_INFO
+        {
+            struct tcp_info info;
+            socklen_t optlen = sizeof(info);
+
+            ZERO_STRUCT(info);
+            ret = getsockopt(sock, IPPROTO_TCP, TCP_INFO, &info, &optlen);
+            if (ret == -1) {
+                ret = errno;
+                perror("TCP_INFO failed");
+                close(sock);
+                return ret;
+            }
+#ifdef HAVE_NETINET_TCP_FSM_H
+/* This is FreeBSD */
+# define __TCP_LISTEN TCPS_LISTEN
+#else
+/* This is Linux */
+# define __TCP_LISTEN TCP_LISTEN
+#endif
+            if (info.tcpi_state != __TCP_LISTEN) {
+                errno = ret = ERANGE;
+                perror("not __TCP_LISTEN => ERANGE...");
+                close(sock);
+                return ret;
+            }
+        }
+#endif /* TCP_INFO */
     }
 
     *_sock = sock;
index dfa46fe46439271ffba0bb9974b3fed714effc8c..5e5661d04b9f730ab9ac2fd6e48e7d990476e1d4 100644 (file)
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
+#ifdef HAVE_NETINET_TCP_FSM_H
+#include <netinet/tcp_fsm.h>
+#endif
 #include <arpa/inet.h>
 #include <netdb.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
 
+#ifdef HAVE_NETINET_TCP_FSM_H
+/* This is FreeBSD */
+# define __TCP_ESTABLISHED TCPS_ESTABLISHED
+# define __TCP_CLOSE TCPS_CLOSED
+#else
+/* This is Linux */
+# define __TCP_ESTABLISHED TCP_ESTABLISHED
+# define __TCP_CLOSE TCP_CLOSE
+#endif
+
 #ifndef ZERO_STRUCT
 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
 #endif
@@ -300,6 +313,9 @@ static void test_sockopt_tcp(void **state)
                .sa_socklen = sizeof(struct sockaddr_in),
        };
        int opt = -1;
+#ifdef TCP_INFO
+       struct tcp_info info;
+#endif
        socklen_t optlen = sizeof(int);
        int rc;
 
@@ -318,9 +334,27 @@ static void test_sockopt_tcp(void **state)
                       &addr.sa.in.sin_addr);
        assert_int_equal(rc, 1);
 
+#ifdef TCP_INFO
+       ZERO_STRUCT(info);
+       optlen = sizeof(info);
+       rc = getsockopt(s, IPPROTO_TCP, TCP_INFO, &info, &optlen);
+       assert_return_code(rc, errno);
+       assert_int_equal(optlen, sizeof(info));
+       printf("info.tcpi_state=0x%x\n", info.tcpi_state);
+       printf("info.tcpi_rto=%u\n", info.tcpi_rto);
+       printf("info.tcpi_rtt=%u\n", info.tcpi_rtt);
+       printf("info.tcpi_rttvar=%u\n", info.tcpi_rttvar);
+       assert_int_equal(info.tcpi_state, __TCP_CLOSE);
+       assert_int_not_equal(info.tcpi_rto, 0);
+       assert_int_equal(info.tcpi_rtt, 0);
+       assert_int_not_equal(info.tcpi_rttvar, 0);
+#endif /* TCP_INFO */
+
        rc = connect(s, &addr.sa.s, addr.sa_socklen);
        assert_int_equal(rc, 0);
 
+       opt = -1;
+       optlen = sizeof(int);
        rc = getsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen);
        assert_return_code(rc, errno);
        assert_int_equal(opt, 0);
@@ -336,6 +370,22 @@ static void test_sockopt_tcp(void **state)
        assert_return_code(rc, errno);
        assert_int_equal(opt, 1);
 
+#ifdef TCP_INFO
+       ZERO_STRUCT(info);
+       optlen = sizeof(info);
+       rc = getsockopt(s, IPPROTO_TCP, TCP_INFO, &info, &optlen);
+       assert_return_code(rc, errno);
+       assert_int_equal(optlen, sizeof(info));
+       printf("info.tcpi_state=0x%x\n", info.tcpi_state);
+       printf("info.tcpi_rto=%u\n", info.tcpi_rto);
+       printf("info.tcpi_rtt=%u\n", info.tcpi_rtt);
+       printf("info.tcpi_rttvar=%u\n", info.tcpi_rttvar);
+       assert_int_equal(info.tcpi_state, __TCP_ESTABLISHED);
+       assert_int_not_equal(info.tcpi_rto, 0);
+       assert_int_not_equal(info.tcpi_rtt, 0);
+       assert_int_not_equal(info.tcpi_rttvar, 0);
+#endif /* TCP_INFO */
+
        close(s);
 }