1 /* 2 * QEMU I/O channel sockets test 3 * 4 * Copyright (c) 2015-2016 Red Hat, Inc. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 * 19 */ 20 21 #include "qemu/osdep.h" 22 #include "io/channel-socket.h" 23 #include "io/channel-util.h" 24 #include "io-channel-helpers.h" 25 #include "qapi/error.h" 26 27 #ifndef AI_ADDRCONFIG 28 # define AI_ADDRCONFIG 0 29 #endif 30 #ifndef EAI_ADDRFAMILY 31 # define EAI_ADDRFAMILY 0 32 #endif 33 34 static int check_bind(const char *hostname, bool *has_proto) 35 { 36 int fd = -1; 37 struct addrinfo ai, *res = NULL; 38 int rc; 39 int ret = -1; 40 41 memset(&ai, 0, sizeof(ai)); 42 ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; 43 ai.ai_family = AF_UNSPEC; 44 ai.ai_socktype = SOCK_STREAM; 45 46 /* lookup */ 47 rc = getaddrinfo(hostname, NULL, &ai, &res); 48 if (rc != 0) { 49 if (rc == EAI_ADDRFAMILY || 50 rc == EAI_FAMILY) { 51 *has_proto = false; 52 goto done; 53 } 54 goto cleanup; 55 } 56 57 fd = qemu_socket(res->ai_family, res->ai_socktype, res->ai_protocol); 58 if (fd < 0) { 59 goto cleanup; 60 } 61 62 if (bind(fd, res->ai_addr, res->ai_addrlen) < 0) { 63 if (errno == EADDRNOTAVAIL) { 64 *has_proto = false; 65 goto done; 66 } 67 goto cleanup; 68 } 69 70 *has_proto = true; 71 done: 72 ret = 0; 73 74 cleanup: 75 if (fd != -1) { 76 close(fd); 77 } 78 if (res) { 79 freeaddrinfo(res); 80 } 81 return ret; 82 } 83 84 static int check_protocol_support(bool *has_ipv4, bool *has_ipv6) 85 { 86 if (check_bind("127.0.0.1", has_ipv4) < 0) { 87 return -1; 88 } 89 if (check_bind("::1", has_ipv6) < 0) { 90 return -1; 91 } 92 93 return 0; 94 } 95 96 97 static void test_io_channel_set_socket_bufs(QIOChannel *src, 98 QIOChannel *dst) 99 { 100 int buflen = 64 * 1024; 101 102 /* 103 * Make the socket buffers small so that we see 104 * the effects of partial reads/writes 105 */ 106 setsockopt(((QIOChannelSocket *)src)->fd, 107 SOL_SOCKET, SO_SNDBUF, 108 (char *)&buflen, 109 sizeof(buflen)); 110 111 setsockopt(((QIOChannelSocket *)dst)->fd, 112 SOL_SOCKET, SO_SNDBUF, 113 (char *)&buflen, 114 sizeof(buflen)); 115 } 116 117 118 static void test_io_channel_setup_sync(SocketAddress *listen_addr, 119 SocketAddress *connect_addr, 120 QIOChannel **src, 121 QIOChannel **dst) 122 { 123 QIOChannelSocket *lioc; 124 125 lioc = qio_channel_socket_new(); 126 qio_channel_socket_listen_sync(lioc, listen_addr, &error_abort); 127 128 if (listen_addr->type == SOCKET_ADDRESS_TYPE_INET) { 129 SocketAddress *laddr = qio_channel_socket_get_local_address( 130 lioc, &error_abort); 131 132 g_free(connect_addr->u.inet.port); 133 connect_addr->u.inet.port = g_strdup(laddr->u.inet.port); 134 135 qapi_free_SocketAddress(laddr); 136 } 137 138 *src = QIO_CHANNEL(qio_channel_socket_new()); 139 qio_channel_socket_connect_sync( 140 QIO_CHANNEL_SOCKET(*src), connect_addr, &error_abort); 141 qio_channel_set_delay(*src, false); 142 143 qio_channel_wait(QIO_CHANNEL(lioc), G_IO_IN); 144 *dst = QIO_CHANNEL(qio_channel_socket_accept(lioc, &error_abort)); 145 g_assert(*dst); 146 147 test_io_channel_set_socket_bufs(*src, *dst); 148 149 object_unref(OBJECT(lioc)); 150 } 151 152 153 struct TestIOChannelData { 154 bool err; 155 GMainLoop *loop; 156 }; 157 158 159 static void test_io_channel_complete(QIOTask *task, 160 gpointer opaque) 161 { 162 struct TestIOChannelData *data = opaque; 163 data->err = qio_task_propagate_error(task, NULL); 164 g_main_loop_quit(data->loop); 165 } 166 167 168 static void test_io_channel_setup_async(SocketAddress *listen_addr, 169 SocketAddress *connect_addr, 170 QIOChannel **src, 171 QIOChannel **dst) 172 { 173 QIOChannelSocket *lioc; 174 struct TestIOChannelData data; 175 176 data.loop = g_main_loop_new(g_main_context_default(), 177 TRUE); 178 179 lioc = qio_channel_socket_new(); 180 qio_channel_socket_listen_async( 181 lioc, listen_addr, 182 test_io_channel_complete, &data, NULL, NULL); 183 184 g_main_loop_run(data.loop); 185 g_main_context_iteration(g_main_context_default(), FALSE); 186 187 g_assert(!data.err); 188 189 if (listen_addr->type == SOCKET_ADDRESS_TYPE_INET) { 190 SocketAddress *laddr = qio_channel_socket_get_local_address( 191 lioc, &error_abort); 192 193 g_free(connect_addr->u.inet.port); 194 connect_addr->u.inet.port = g_strdup(laddr->u.inet.port); 195 196 qapi_free_SocketAddress(laddr); 197 } 198 199 *src = QIO_CHANNEL(qio_channel_socket_new()); 200 201 qio_channel_socket_connect_async( 202 QIO_CHANNEL_SOCKET(*src), connect_addr, 203 test_io_channel_complete, &data, NULL, NULL); 204 205 g_main_loop_run(data.loop); 206 g_main_context_iteration(g_main_context_default(), FALSE); 207 208 g_assert(!data.err); 209 210 qio_channel_wait(QIO_CHANNEL(lioc), G_IO_IN); 211 *dst = QIO_CHANNEL(qio_channel_socket_accept(lioc, &error_abort)); 212 g_assert(*dst); 213 214 qio_channel_set_delay(*src, false); 215 test_io_channel_set_socket_bufs(*src, *dst); 216 217 object_unref(OBJECT(lioc)); 218 219 g_main_loop_unref(data.loop); 220 } 221 222 223 static void test_io_channel(bool async, 224 SocketAddress *listen_addr, 225 SocketAddress *connect_addr, 226 bool passFD) 227 { 228 QIOChannel *src, *dst; 229 QIOChannelTest *test; 230 if (async) { 231 test_io_channel_setup_async(listen_addr, connect_addr, &src, &dst); 232 233 g_assert(!passFD || 234 qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS)); 235 g_assert(!passFD || 236 qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS)); 237 g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN)); 238 g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN)); 239 240 test = qio_channel_test_new(); 241 qio_channel_test_run_threads(test, true, src, dst); 242 qio_channel_test_validate(test); 243 244 object_unref(OBJECT(src)); 245 object_unref(OBJECT(dst)); 246 247 test_io_channel_setup_async(listen_addr, connect_addr, &src, &dst); 248 249 g_assert(!passFD || 250 qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS)); 251 g_assert(!passFD || 252 qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS)); 253 g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN)); 254 g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN)); 255 256 test = qio_channel_test_new(); 257 qio_channel_test_run_threads(test, false, src, dst); 258 qio_channel_test_validate(test); 259 260 object_unref(OBJECT(src)); 261 object_unref(OBJECT(dst)); 262 } else { 263 test_io_channel_setup_sync(listen_addr, connect_addr, &src, &dst); 264 265 g_assert(!passFD || 266 qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS)); 267 g_assert(!passFD || 268 qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS)); 269 g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN)); 270 g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN)); 271 272 test = qio_channel_test_new(); 273 qio_channel_test_run_threads(test, true, src, dst); 274 qio_channel_test_validate(test); 275 276 object_unref(OBJECT(src)); 277 object_unref(OBJECT(dst)); 278 279 test_io_channel_setup_sync(listen_addr, connect_addr, &src, &dst); 280 281 g_assert(!passFD || 282 qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS)); 283 g_assert(!passFD || 284 qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS)); 285 g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN)); 286 g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN)); 287 288 test = qio_channel_test_new(); 289 qio_channel_test_run_threads(test, false, src, dst); 290 qio_channel_test_validate(test); 291 292 object_unref(OBJECT(src)); 293 object_unref(OBJECT(dst)); 294 } 295 } 296 297 298 static void test_io_channel_ipv4(bool async) 299 { 300 SocketAddress *listen_addr = g_new0(SocketAddress, 1); 301 SocketAddress *connect_addr = g_new0(SocketAddress, 1); 302 303 listen_addr->type = SOCKET_ADDRESS_TYPE_INET; 304 listen_addr->u.inet = (InetSocketAddress) { 305 .host = g_strdup("127.0.0.1"), 306 .port = NULL, /* Auto-select */ 307 }; 308 309 connect_addr->type = SOCKET_ADDRESS_TYPE_INET; 310 connect_addr->u.inet = (InetSocketAddress) { 311 .host = g_strdup("127.0.0.1"), 312 .port = NULL, /* Filled in later */ 313 }; 314 315 test_io_channel(async, listen_addr, connect_addr, false); 316 317 qapi_free_SocketAddress(listen_addr); 318 qapi_free_SocketAddress(connect_addr); 319 } 320 321 322 static void test_io_channel_ipv4_sync(void) 323 { 324 return test_io_channel_ipv4(false); 325 } 326 327 328 static void test_io_channel_ipv4_async(void) 329 { 330 return test_io_channel_ipv4(true); 331 } 332 333 334 static void test_io_channel_ipv6(bool async) 335 { 336 SocketAddress *listen_addr = g_new0(SocketAddress, 1); 337 SocketAddress *connect_addr = g_new0(SocketAddress, 1); 338 339 listen_addr->type = SOCKET_ADDRESS_TYPE_INET; 340 listen_addr->u.inet = (InetSocketAddress) { 341 .host = g_strdup("::1"), 342 .port = NULL, /* Auto-select */ 343 }; 344 345 connect_addr->type = SOCKET_ADDRESS_TYPE_INET; 346 connect_addr->u.inet = (InetSocketAddress) { 347 .host = g_strdup("::1"), 348 .port = NULL, /* Filled in later */ 349 }; 350 351 test_io_channel(async, listen_addr, connect_addr, false); 352 353 qapi_free_SocketAddress(listen_addr); 354 qapi_free_SocketAddress(connect_addr); 355 } 356 357 358 static void test_io_channel_ipv6_sync(void) 359 { 360 return test_io_channel_ipv6(false); 361 } 362 363 364 static void test_io_channel_ipv6_async(void) 365 { 366 return test_io_channel_ipv6(true); 367 } 368 369 370 #ifndef _WIN32 371 static void test_io_channel_unix(bool async) 372 { 373 SocketAddress *listen_addr = g_new0(SocketAddress, 1); 374 SocketAddress *connect_addr = g_new0(SocketAddress, 1); 375 376 #define TEST_SOCKET "test-io-channel-socket.sock" 377 listen_addr->type = SOCKET_ADDRESS_TYPE_UNIX; 378 listen_addr->u.q_unix.path = g_strdup(TEST_SOCKET); 379 380 connect_addr->type = SOCKET_ADDRESS_TYPE_UNIX; 381 connect_addr->u.q_unix.path = g_strdup(TEST_SOCKET); 382 383 test_io_channel(async, listen_addr, connect_addr, true); 384 385 qapi_free_SocketAddress(listen_addr); 386 qapi_free_SocketAddress(connect_addr); 387 g_assert(g_file_test(TEST_SOCKET, G_FILE_TEST_EXISTS) == FALSE); 388 } 389 390 391 static void test_io_channel_unix_sync(void) 392 { 393 return test_io_channel_unix(false); 394 } 395 396 397 static void test_io_channel_unix_async(void) 398 { 399 return test_io_channel_unix(true); 400 } 401 402 static void test_io_channel_unix_fd_pass(void) 403 { 404 SocketAddress *listen_addr = g_new0(SocketAddress, 1); 405 SocketAddress *connect_addr = g_new0(SocketAddress, 1); 406 QIOChannel *src, *dst; 407 int testfd; 408 int fdsend[3]; 409 int *fdrecv = NULL; 410 size_t nfdrecv = 0; 411 size_t i; 412 char bufsend[12], bufrecv[12]; 413 struct iovec iosend[1], iorecv[1]; 414 415 #define TEST_SOCKET "test-io-channel-socket.sock" 416 #define TEST_FILE "test-io-channel-socket.txt" 417 418 testfd = open(TEST_FILE, O_RDWR|O_TRUNC|O_CREAT, 0700); 419 g_assert(testfd != -1); 420 fdsend[0] = testfd; 421 fdsend[1] = testfd; 422 fdsend[2] = testfd; 423 424 listen_addr->type = SOCKET_ADDRESS_TYPE_UNIX; 425 listen_addr->u.q_unix.path = g_strdup(TEST_SOCKET); 426 427 connect_addr->type = SOCKET_ADDRESS_TYPE_UNIX; 428 connect_addr->u.q_unix.path = g_strdup(TEST_SOCKET); 429 430 test_io_channel_setup_sync(listen_addr, connect_addr, &src, &dst); 431 432 memcpy(bufsend, "Hello World", G_N_ELEMENTS(bufsend)); 433 434 iosend[0].iov_base = bufsend; 435 iosend[0].iov_len = G_N_ELEMENTS(bufsend); 436 437 iorecv[0].iov_base = bufrecv; 438 iorecv[0].iov_len = G_N_ELEMENTS(bufrecv); 439 440 g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS)); 441 g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS)); 442 443 qio_channel_writev_full(src, 444 iosend, 445 G_N_ELEMENTS(iosend), 446 fdsend, 447 G_N_ELEMENTS(fdsend), 448 &error_abort); 449 450 qio_channel_readv_full(dst, 451 iorecv, 452 G_N_ELEMENTS(iorecv), 453 &fdrecv, 454 &nfdrecv, 455 &error_abort); 456 457 g_assert(nfdrecv == G_N_ELEMENTS(fdsend)); 458 /* Each recvd FD should be different from sent FD */ 459 for (i = 0; i < nfdrecv; i++) { 460 g_assert_cmpint(fdrecv[i], !=, testfd); 461 } 462 /* Each recvd FD should be different from each other */ 463 g_assert_cmpint(fdrecv[0], !=, fdrecv[1]); 464 g_assert_cmpint(fdrecv[0], !=, fdrecv[2]); 465 g_assert_cmpint(fdrecv[1], !=, fdrecv[2]); 466 467 /* Check the I/O buf we sent at the same time matches */ 468 g_assert(memcmp(bufsend, bufrecv, G_N_ELEMENTS(bufsend)) == 0); 469 470 /* Write some data into the FD we received */ 471 g_assert(write(fdrecv[0], bufsend, G_N_ELEMENTS(bufsend)) == 472 G_N_ELEMENTS(bufsend)); 473 474 /* Read data from the original FD and make sure it matches */ 475 memset(bufrecv, 0, G_N_ELEMENTS(bufrecv)); 476 g_assert(lseek(testfd, 0, SEEK_SET) == 0); 477 g_assert(read(testfd, bufrecv, G_N_ELEMENTS(bufrecv)) == 478 G_N_ELEMENTS(bufrecv)); 479 g_assert(memcmp(bufsend, bufrecv, G_N_ELEMENTS(bufsend)) == 0); 480 481 object_unref(OBJECT(src)); 482 object_unref(OBJECT(dst)); 483 qapi_free_SocketAddress(listen_addr); 484 qapi_free_SocketAddress(connect_addr); 485 unlink(TEST_SOCKET); 486 unlink(TEST_FILE); 487 close(testfd); 488 for (i = 0; i < nfdrecv; i++) { 489 close(fdrecv[i]); 490 } 491 g_free(fdrecv); 492 } 493 494 static void test_io_channel_unix_listen_cleanup(void) 495 { 496 QIOChannelSocket *ioc; 497 struct sockaddr_un un; 498 int sock; 499 500 #define TEST_SOCKET "test-io-channel-socket.sock" 501 502 ioc = qio_channel_socket_new(); 503 504 /* Manually bind ioc without calling the qio api to avoid setting 505 * the LISTEN feature */ 506 sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 507 memset(&un, 0, sizeof(un)); 508 un.sun_family = AF_UNIX; 509 snprintf(un.sun_path, sizeof(un.sun_path), "%s", TEST_SOCKET); 510 unlink(TEST_SOCKET); 511 bind(sock, (struct sockaddr *)&un, sizeof(un)); 512 ioc->fd = sock; 513 ioc->localAddrLen = sizeof(ioc->localAddr); 514 getsockname(sock, (struct sockaddr *)&ioc->localAddr, 515 &ioc->localAddrLen); 516 517 g_assert(g_file_test(TEST_SOCKET, G_FILE_TEST_EXISTS)); 518 object_unref(OBJECT(ioc)); 519 g_assert(g_file_test(TEST_SOCKET, G_FILE_TEST_EXISTS)); 520 521 unlink(TEST_SOCKET); 522 } 523 524 #endif /* _WIN32 */ 525 526 527 static void test_io_channel_ipv4_fd(void) 528 { 529 QIOChannel *ioc; 530 int fd = -1; 531 struct sockaddr_in sa = { 532 .sin_family = AF_INET, 533 .sin_addr = { 534 .s_addr = htonl(INADDR_LOOPBACK), 535 } 536 /* Leave port unset for auto-assign */ 537 }; 538 socklen_t salen = sizeof(sa); 539 540 fd = socket(AF_INET, SOCK_STREAM, 0); 541 g_assert_cmpint(fd, >, -1); 542 543 g_assert_cmpint(bind(fd, (struct sockaddr *)&sa, salen), ==, 0); 544 545 ioc = qio_channel_new_fd(fd, &error_abort); 546 547 g_assert_cmpstr(object_get_typename(OBJECT(ioc)), 548 ==, 549 TYPE_QIO_CHANNEL_SOCKET); 550 551 object_unref(OBJECT(ioc)); 552 } 553 554 555 int main(int argc, char **argv) 556 { 557 bool has_ipv4, has_ipv6; 558 559 module_call_init(MODULE_INIT_QOM); 560 socket_init(); 561 562 g_test_init(&argc, &argv, NULL); 563 564 /* We're creating actual IPv4/6 sockets, so we should 565 * check if the host running tests actually supports 566 * each protocol to avoid breaking tests on machines 567 * with either IPv4 or IPv6 disabled. 568 */ 569 if (check_protocol_support(&has_ipv4, &has_ipv6) < 0) { 570 return 1; 571 } 572 573 if (has_ipv4) { 574 g_test_add_func("/io/channel/socket/ipv4-sync", 575 test_io_channel_ipv4_sync); 576 g_test_add_func("/io/channel/socket/ipv4-async", 577 test_io_channel_ipv4_async); 578 g_test_add_func("/io/channel/socket/ipv4-fd", 579 test_io_channel_ipv4_fd); 580 } 581 if (has_ipv6) { 582 g_test_add_func("/io/channel/socket/ipv6-sync", 583 test_io_channel_ipv6_sync); 584 g_test_add_func("/io/channel/socket/ipv6-async", 585 test_io_channel_ipv6_async); 586 } 587 588 #ifndef _WIN32 589 g_test_add_func("/io/channel/socket/unix-sync", 590 test_io_channel_unix_sync); 591 g_test_add_func("/io/channel/socket/unix-async", 592 test_io_channel_unix_async); 593 g_test_add_func("/io/channel/socket/unix-fd-pass", 594 test_io_channel_unix_fd_pass); 595 g_test_add_func("/io/channel/socket/unix-listen-cleanup", 596 test_io_channel_unix_listen_cleanup); 597 #endif /* _WIN32 */ 598 599 return g_test_run(); 600 } 601