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;
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),