tests: add new test test_bind_ipv4_addr_in_use()
authorMichael Adam <obnox@samba.org>
Sat, 31 May 2014 01:35:22 +0000 (03:35 +0200)
committerMichael Adam <obnox@samba.org>
Sun, 1 Jun 2014 08:03:32 +0000 (10:03 +0200)
This tests binding an address that is already in use.

Signed-off-by: Michael Adam <obnox@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
tests/test_echo_tcp_bind.c

index 51528c29c4ecb1e5907d6d0e04ac3f2e56def644..c699b06b27616049b3575361a9385bc769bf2ed4 100644 (file)
@@ -154,6 +154,160 @@ static void test_bind_ipv4(void **state)
        close(s);
 }
 
+static void test_bind_ipv4_addr_in_use(void **state)
+{
+       struct sockaddr_in sin, sin2;
+       socklen_t slen = sizeof(struct sockaddr_in);
+       int rc;
+       int s, s2;
+
+       (void) state; /* unused */
+
+       s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+       assert_return_code(s, errno);
+
+       /*
+        * Try to bind to the same address as already bound by a
+        * different process.
+        */
+
+       /* Without specifying the port - success */
+
+       ZERO_STRUCT(sin);
+       sin.sin_family = AF_INET;
+       rc = inet_pton(AF_INET, torture_server_address(AF_INET), &sin.sin_addr);
+       assert_int_equal(rc, 1);
+       rc = bind(s, (struct sockaddr *)&sin, slen);
+       assert_return_code(rc, errno);
+
+       close(s);
+
+       s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+       assert_return_code(s, errno);
+
+#if 0
+       /* specify the same port - fail with EADDRINUSE. */
+
+       /* Not supported by socket_wrapper yet. ==> TODO! */
+
+       ZERO_STRUCT(sin);
+       sin.sin_family = AF_INET,
+       sin.sin_port = htons(torture_server_port());
+       rc = inet_pton(AF_INET, torture_server_address(AF_INET), &sin.sin_addr);
+       assert_int_equal(rc, 1);
+
+       rc = bind(s, (struct sockaddr *)&sin, slen);
+       assert_int_equal(rc, -1);
+       assert_int_equal(errno, EADDRINUSE);
+#endif
+
+       /*
+        * Try double binding when the firs bind is with port == 0
+        */
+
+       ZERO_STRUCT(sin);
+       sin.sin_family = AF_INET;
+
+       rc = inet_pton(AF_INET, "127.0.0.20", &sin.sin_addr);
+       assert_int_equal(rc, 1);
+
+       rc = bind(s, (struct sockaddr *)&sin, slen);
+       assert_return_code(rc, errno);
+
+       /*
+        * Open a second socket locally and try to bind to the same address.
+        */
+
+        /* Succeeds with port == 0 */
+
+       s2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+       assert_return_code(s, errno);
+
+       ZERO_STRUCT(sin2);
+       sin2.sin_family = AF_INET;
+
+       rc = inet_pton(AF_INET, "127.0.0.20", &sin2.sin_addr);
+       assert_int_equal(rc, 1);
+
+       rc = bind(s2, (struct sockaddr *)&sin2, slen);
+       assert_return_code(rc, errno);
+
+       close(s2);
+
+       /* second bind with port != 0  - succeeds */
+
+       s2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+       assert_return_code(s, errno);
+
+       ZERO_STRUCT(sin2);
+       sin2.sin_family = AF_INET;
+       sin2.sin_port = htons(12345);
+
+       rc = inet_pton(AF_INET, "127.0.0.20", &sin2.sin_addr);
+       assert_int_equal(rc, 1);
+
+       rc = bind(s2, (struct sockaddr *)&sin2, slen);
+       assert_return_code(rc, errno);
+
+       close(s2);
+       close(s);
+
+       /*
+        * Try double binding when the first bind is with port != 0
+        */
+
+       s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+       assert_return_code(s, errno);
+
+       ZERO_STRUCT(sin);
+       sin.sin_family = AF_INET;
+       sin.sin_port = htons(12345);
+
+       rc = inet_pton(AF_INET, "127.0.0.20", &sin.sin_addr);
+       assert_int_equal(rc, 1);
+
+       rc = bind(s, (struct sockaddr *)&sin, slen);
+       assert_return_code(rc, errno);
+
+       /*
+        * Open a second socket locally and try to bind to the same address.
+        */
+
+        /* Succeeds with port == 0 */
+
+       s2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+       assert_return_code(s, errno);
+
+       ZERO_STRUCT(sin2);
+       sin2.sin_family = AF_INET;
+
+       rc = inet_pton(AF_INET, "127.0.0.20", &sin2.sin_addr);
+       assert_int_equal(rc, 1);
+
+       rc = bind(s2, (struct sockaddr *)&sin2, slen);
+       assert_return_code(rc, errno);
+
+       close(s2);
+
+       /* with same port as above - fail with EADDRINUSE */
+
+       s2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+       assert_return_code(s, errno);
+
+       ZERO_STRUCT(sin2);
+       sin2.sin_family = AF_INET;
+       sin2.sin_port = htons(12345);
+
+       rc = inet_pton(AF_INET, "127.0.0.20", &sin2.sin_addr);
+       assert_int_equal(rc, 1);
+
+       rc = bind(s2, (struct sockaddr *)&sin2, slen);
+       assert_int_equal(rc, -1);
+       assert_int_equal(errno, EADDRINUSE);
+
+       close(s);
+}
+
 static void test_bindresvport_ipv4(void **state)
 {
        struct sockaddr_in sin;
@@ -312,6 +466,9 @@ int main(void) {
                unit_test_setup_teardown(test_bind_ipv4,
                                         setup_echo_srv_tcp_ipv4,
                                         teardown),
+               unit_test_setup_teardown(test_bind_ipv4_addr_in_use,
+                                        setup_echo_srv_tcp_ipv4,
+                                        teardown),
                unit_test_setup_teardown(test_bindresvport_ipv4,
                                         setup_echo_srv_tcp_ipv4,
                                         teardown),