158dc31f1SDaniel P. Berrange /* 258dc31f1SDaniel P. Berrange * Tests for util/qemu-sockets.c 358dc31f1SDaniel P. Berrange * 458dc31f1SDaniel P. Berrange * Copyright 2018 Red Hat, Inc. 558dc31f1SDaniel P. Berrange * 658dc31f1SDaniel P. Berrange * This program is free software; you can redistribute it and/or modify 758dc31f1SDaniel P. Berrange * it under the terms of the GNU General Public License as published by 858dc31f1SDaniel P. Berrange * the Free Software Foundation; either version 2 of the License, or 958dc31f1SDaniel P. Berrange * (at your option) any later version. 1058dc31f1SDaniel P. Berrange * 1158dc31f1SDaniel P. Berrange * This program is distributed in the hope that it will be useful, 1258dc31f1SDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 1358dc31f1SDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1458dc31f1SDaniel P. Berrange * GNU General Public License for more details. 1558dc31f1SDaniel P. Berrange * 1658dc31f1SDaniel P. Berrange * You should have received a copy of the GNU General Public License 1758dc31f1SDaniel P. Berrange * along with this library; if not, see <http://www.gnu.org/licenses/>. 1858dc31f1SDaniel P. Berrange * 1958dc31f1SDaniel P. Berrange */ 2058dc31f1SDaniel P. Berrange 2158dc31f1SDaniel P. Berrange #include "qemu/osdep.h" 2258dc31f1SDaniel P. Berrange #include "qemu/sockets.h" 2358dc31f1SDaniel P. Berrange #include "qapi/error.h" 2458dc31f1SDaniel P. Berrange #include "socket-helpers.h" 2530bdb3c5SDaniel P. Berrange #include "monitor/monitor.h" 2658dc31f1SDaniel P. Berrange 2758dc31f1SDaniel P. Berrange static void test_fd_is_socket_bad(void) 2858dc31f1SDaniel P. Berrange { 2958dc31f1SDaniel P. Berrange char *tmp = g_strdup("qemu-test-util-sockets-XXXXXX"); 3058dc31f1SDaniel P. Berrange int fd = mkstemp(tmp); 3158dc31f1SDaniel P. Berrange if (fd != 0) { 3258dc31f1SDaniel P. Berrange unlink(tmp); 3358dc31f1SDaniel P. Berrange } 3458dc31f1SDaniel P. Berrange g_free(tmp); 3558dc31f1SDaniel P. Berrange 3658dc31f1SDaniel P. Berrange g_assert(fd >= 0); 3758dc31f1SDaniel P. Berrange 3858dc31f1SDaniel P. Berrange g_assert(!fd_is_socket(fd)); 3958dc31f1SDaniel P. Berrange close(fd); 4058dc31f1SDaniel P. Berrange } 4158dc31f1SDaniel P. Berrange 4258dc31f1SDaniel P. Berrange static void test_fd_is_socket_good(void) 4358dc31f1SDaniel P. Berrange { 4458dc31f1SDaniel P. Berrange int fd = qemu_socket(PF_INET, SOCK_STREAM, 0); 4558dc31f1SDaniel P. Berrange 4658dc31f1SDaniel P. Berrange g_assert(fd >= 0); 4758dc31f1SDaniel P. Berrange 4858dc31f1SDaniel P. Berrange g_assert(fd_is_socket(fd)); 4958dc31f1SDaniel P. Berrange close(fd); 5058dc31f1SDaniel P. Berrange } 5158dc31f1SDaniel P. Berrange 5230bdb3c5SDaniel P. Berrange static int mon_fd = -1; 5330bdb3c5SDaniel P. Berrange static const char *mon_fdname; 54947e4744SKevin Wolf __thread Monitor *cur_mon; 5530bdb3c5SDaniel P. Berrange 5630bdb3c5SDaniel P. Berrange int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp) 5730bdb3c5SDaniel P. Berrange { 5830bdb3c5SDaniel P. Berrange g_assert(cur_mon); 5930bdb3c5SDaniel P. Berrange g_assert(mon == cur_mon); 6030bdb3c5SDaniel P. Berrange if (mon_fd == -1 || !g_str_equal(mon_fdname, fdname)) { 6130bdb3c5SDaniel P. Berrange error_setg(errp, "No fd named %s", fdname); 6230bdb3c5SDaniel P. Berrange return -1; 6330bdb3c5SDaniel P. Berrange } 6430bdb3c5SDaniel P. Berrange return dup(mon_fd); 6530bdb3c5SDaniel P. Berrange } 6630bdb3c5SDaniel P. Berrange 67d2a71d74SThomas Huth /* 68947e4744SKevin Wolf * Syms of stubs in libqemuutil.a are discarded at .o file 69947e4744SKevin Wolf * granularity. To replace monitor_get_fd() and monitor_cur(), we 70947e4744SKevin Wolf * must ensure that we also replace any other symbol that is used in 71947e4744SKevin Wolf * the binary and would be taken from the same stub object file, 7230bdb3c5SDaniel P. Berrange * otherwise we get duplicate syms at link time. 7330bdb3c5SDaniel P. Berrange */ 74947e4744SKevin Wolf Monitor *monitor_cur(void) { return cur_mon; } 75130d4824SMarkus Armbruster Monitor *monitor_set_cur(Coroutine *co, Monitor *mon) { abort(); } 76637de4dbSMarkus Armbruster int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); } 7730bdb3c5SDaniel P. Berrange 788330bd53SYonggang Luo #ifndef _WIN32 791723d6b1SDaniel P. Berrange static void test_socket_fd_pass_name_good(void) 8030bdb3c5SDaniel P. Berrange { 8130bdb3c5SDaniel P. Berrange SocketAddress addr; 8230bdb3c5SDaniel P. Berrange int fd; 8330bdb3c5SDaniel P. Berrange 8430bdb3c5SDaniel P. Berrange cur_mon = g_malloc(1); /* Fake a monitor */ 8530bdb3c5SDaniel P. Berrange mon_fdname = "myfd"; 8630bdb3c5SDaniel P. Berrange mon_fd = qemu_socket(AF_INET, SOCK_STREAM, 0); 8730bdb3c5SDaniel P. Berrange g_assert_cmpint(mon_fd, >, STDERR_FILENO); 8830bdb3c5SDaniel P. Berrange 8930bdb3c5SDaniel P. Berrange addr.type = SOCKET_ADDRESS_TYPE_FD; 9030bdb3c5SDaniel P. Berrange addr.u.fd.str = g_strdup(mon_fdname); 9130bdb3c5SDaniel P. Berrange 9230bdb3c5SDaniel P. Berrange fd = socket_connect(&addr, &error_abort); 9330bdb3c5SDaniel P. Berrange g_assert_cmpint(fd, !=, -1); 9430bdb3c5SDaniel P. Berrange g_assert_cmpint(fd, !=, mon_fd); 9530bdb3c5SDaniel P. Berrange close(fd); 9630bdb3c5SDaniel P. Berrange 97e5b6353cSJuan Quintela fd = socket_listen(&addr, 1, &error_abort); 9830bdb3c5SDaniel P. Berrange g_assert_cmpint(fd, !=, -1); 9930bdb3c5SDaniel P. Berrange g_assert_cmpint(fd, !=, mon_fd); 10030bdb3c5SDaniel P. Berrange close(fd); 10130bdb3c5SDaniel P. Berrange 10230bdb3c5SDaniel P. Berrange g_free(addr.u.fd.str); 10330bdb3c5SDaniel P. Berrange mon_fdname = NULL; 10430bdb3c5SDaniel P. Berrange close(mon_fd); 10530bdb3c5SDaniel P. Berrange mon_fd = -1; 10630bdb3c5SDaniel P. Berrange g_free(cur_mon); 10730bdb3c5SDaniel P. Berrange cur_mon = NULL; 10830bdb3c5SDaniel P. Berrange } 10930bdb3c5SDaniel P. Berrange 1101723d6b1SDaniel P. Berrange static void test_socket_fd_pass_name_bad(void) 11130bdb3c5SDaniel P. Berrange { 11230bdb3c5SDaniel P. Berrange SocketAddress addr; 11330bdb3c5SDaniel P. Berrange Error *err = NULL; 11430bdb3c5SDaniel P. Berrange int fd; 11530bdb3c5SDaniel P. Berrange 11630bdb3c5SDaniel P. Berrange cur_mon = g_malloc(1); /* Fake a monitor */ 11730bdb3c5SDaniel P. Berrange mon_fdname = "myfd"; 11830bdb3c5SDaniel P. Berrange mon_fd = dup(STDOUT_FILENO); 11930bdb3c5SDaniel P. Berrange g_assert_cmpint(mon_fd, >, STDERR_FILENO); 12030bdb3c5SDaniel P. Berrange 12130bdb3c5SDaniel P. Berrange addr.type = SOCKET_ADDRESS_TYPE_FD; 12230bdb3c5SDaniel P. Berrange addr.u.fd.str = g_strdup(mon_fdname); 12330bdb3c5SDaniel P. Berrange 12430bdb3c5SDaniel P. Berrange fd = socket_connect(&addr, &err); 12530bdb3c5SDaniel P. Berrange g_assert_cmpint(fd, ==, -1); 12630bdb3c5SDaniel P. Berrange error_free_or_abort(&err); 12730bdb3c5SDaniel P. Berrange 128e5b6353cSJuan Quintela fd = socket_listen(&addr, 1, &err); 12930bdb3c5SDaniel P. Berrange g_assert_cmpint(fd, ==, -1); 13030bdb3c5SDaniel P. Berrange error_free_or_abort(&err); 13130bdb3c5SDaniel P. Berrange 13230bdb3c5SDaniel P. Berrange g_free(addr.u.fd.str); 13330bdb3c5SDaniel P. Berrange mon_fdname = NULL; 13430bdb3c5SDaniel P. Berrange close(mon_fd); 13530bdb3c5SDaniel P. Berrange mon_fd = -1; 13630bdb3c5SDaniel P. Berrange g_free(cur_mon); 13730bdb3c5SDaniel P. Berrange cur_mon = NULL; 13830bdb3c5SDaniel P. Berrange } 13930bdb3c5SDaniel P. Berrange 1401723d6b1SDaniel P. Berrange static void test_socket_fd_pass_name_nomon(void) 1411723d6b1SDaniel P. Berrange { 1421723d6b1SDaniel P. Berrange SocketAddress addr; 1431723d6b1SDaniel P. Berrange Error *err = NULL; 1441723d6b1SDaniel P. Berrange int fd; 1451723d6b1SDaniel P. Berrange 1461723d6b1SDaniel P. Berrange g_assert(cur_mon == NULL); 1471723d6b1SDaniel P. Berrange 1481723d6b1SDaniel P. Berrange addr.type = SOCKET_ADDRESS_TYPE_FD; 1491723d6b1SDaniel P. Berrange addr.u.fd.str = g_strdup("myfd"); 1501723d6b1SDaniel P. Berrange 1511723d6b1SDaniel P. Berrange fd = socket_connect(&addr, &err); 1521723d6b1SDaniel P. Berrange g_assert_cmpint(fd, ==, -1); 1531723d6b1SDaniel P. Berrange error_free_or_abort(&err); 1541723d6b1SDaniel P. Berrange 155e5b6353cSJuan Quintela fd = socket_listen(&addr, 1, &err); 1561723d6b1SDaniel P. Berrange g_assert_cmpint(fd, ==, -1); 1571723d6b1SDaniel P. Berrange error_free_or_abort(&err); 1581723d6b1SDaniel P. Berrange 1591723d6b1SDaniel P. Berrange g_free(addr.u.fd.str); 1601723d6b1SDaniel P. Berrange } 1611723d6b1SDaniel P. Berrange 1621723d6b1SDaniel P. Berrange 1631723d6b1SDaniel P. Berrange static void test_socket_fd_pass_num_good(void) 1641723d6b1SDaniel P. Berrange { 1651723d6b1SDaniel P. Berrange SocketAddress addr; 1661723d6b1SDaniel P. Berrange int fd, sfd; 1671723d6b1SDaniel P. Berrange 1681723d6b1SDaniel P. Berrange g_assert(cur_mon == NULL); 1691723d6b1SDaniel P. Berrange sfd = qemu_socket(AF_INET, SOCK_STREAM, 0); 1701723d6b1SDaniel P. Berrange g_assert_cmpint(sfd, >, STDERR_FILENO); 1711723d6b1SDaniel P. Berrange 1721723d6b1SDaniel P. Berrange addr.type = SOCKET_ADDRESS_TYPE_FD; 1731723d6b1SDaniel P. Berrange addr.u.fd.str = g_strdup_printf("%d", sfd); 1741723d6b1SDaniel P. Berrange 1751723d6b1SDaniel P. Berrange fd = socket_connect(&addr, &error_abort); 1761723d6b1SDaniel P. Berrange g_assert_cmpint(fd, ==, sfd); 1771723d6b1SDaniel P. Berrange 178e5b6353cSJuan Quintela fd = socket_listen(&addr, 1, &error_abort); 1791723d6b1SDaniel P. Berrange g_assert_cmpint(fd, ==, sfd); 1801723d6b1SDaniel P. Berrange 1811723d6b1SDaniel P. Berrange g_free(addr.u.fd.str); 1821723d6b1SDaniel P. Berrange close(sfd); 1831723d6b1SDaniel P. Berrange } 1841723d6b1SDaniel P. Berrange 1851723d6b1SDaniel P. Berrange static void test_socket_fd_pass_num_bad(void) 1861723d6b1SDaniel P. Berrange { 1871723d6b1SDaniel P. Berrange SocketAddress addr; 1881723d6b1SDaniel P. Berrange Error *err = NULL; 1891723d6b1SDaniel P. Berrange int fd, sfd; 1901723d6b1SDaniel P. Berrange 1911723d6b1SDaniel P. Berrange g_assert(cur_mon == NULL); 1921723d6b1SDaniel P. Berrange sfd = dup(STDOUT_FILENO); 1931723d6b1SDaniel P. Berrange 1941723d6b1SDaniel P. Berrange addr.type = SOCKET_ADDRESS_TYPE_FD; 1951723d6b1SDaniel P. Berrange addr.u.fd.str = g_strdup_printf("%d", sfd); 1961723d6b1SDaniel P. Berrange 1971723d6b1SDaniel P. Berrange fd = socket_connect(&addr, &err); 1981723d6b1SDaniel P. Berrange g_assert_cmpint(fd, ==, -1); 1991723d6b1SDaniel P. Berrange error_free_or_abort(&err); 2001723d6b1SDaniel P. Berrange 201e5b6353cSJuan Quintela fd = socket_listen(&addr, 1, &err); 2021723d6b1SDaniel P. Berrange g_assert_cmpint(fd, ==, -1); 2031723d6b1SDaniel P. Berrange error_free_or_abort(&err); 2041723d6b1SDaniel P. Berrange 2051723d6b1SDaniel P. Berrange g_free(addr.u.fd.str); 2061723d6b1SDaniel P. Berrange close(sfd); 2071723d6b1SDaniel P. Berrange } 2081723d6b1SDaniel P. Berrange 2091723d6b1SDaniel P. Berrange static void test_socket_fd_pass_num_nocli(void) 2101723d6b1SDaniel P. Berrange { 2111723d6b1SDaniel P. Berrange SocketAddress addr; 2121723d6b1SDaniel P. Berrange Error *err = NULL; 2131723d6b1SDaniel P. Berrange int fd; 2141723d6b1SDaniel P. Berrange 2151723d6b1SDaniel P. Berrange cur_mon = g_malloc(1); /* Fake a monitor */ 2161723d6b1SDaniel P. Berrange 2171723d6b1SDaniel P. Berrange addr.type = SOCKET_ADDRESS_TYPE_FD; 2181723d6b1SDaniel P. Berrange addr.u.fd.str = g_strdup_printf("%d", STDOUT_FILENO); 2191723d6b1SDaniel P. Berrange 2201723d6b1SDaniel P. Berrange fd = socket_connect(&addr, &err); 2211723d6b1SDaniel P. Berrange g_assert_cmpint(fd, ==, -1); 2221723d6b1SDaniel P. Berrange error_free_or_abort(&err); 2231723d6b1SDaniel P. Berrange 224e5b6353cSJuan Quintela fd = socket_listen(&addr, 1, &err); 2251723d6b1SDaniel P. Berrange g_assert_cmpint(fd, ==, -1); 2261723d6b1SDaniel P. Berrange error_free_or_abort(&err); 2271723d6b1SDaniel P. Berrange 2281723d6b1SDaniel P. Berrange g_free(addr.u.fd.str); 2291723d6b1SDaniel P. Berrange } 2308330bd53SYonggang Luo #endif 2311723d6b1SDaniel P. Berrange 2328acefc79SMarkus Armbruster #ifdef CONFIG_LINUX 233a72f6754SMarkus Armbruster 234a72f6754SMarkus Armbruster #define ABSTRACT_SOCKET_VARIANTS 3 235a72f6754SMarkus Armbruster 236a72f6754SMarkus Armbruster typedef struct { 237a72f6754SMarkus Armbruster SocketAddress *server, *client[ABSTRACT_SOCKET_VARIANTS]; 238a72f6754SMarkus Armbruster bool expect_connect[ABSTRACT_SOCKET_VARIANTS]; 239a72f6754SMarkus Armbruster } abstract_socket_matrix_row; 240a72f6754SMarkus Armbruster 2414d3a329aSxiaoqiang zhao static gpointer unix_client_thread_func(gpointer user_data) 2424d3a329aSxiaoqiang zhao { 243a72f6754SMarkus Armbruster abstract_socket_matrix_row *row = user_data; 244a72f6754SMarkus Armbruster Error *err = NULL; 245a72f6754SMarkus Armbruster int i, fd; 2464d3a329aSxiaoqiang zhao 247a72f6754SMarkus Armbruster for (i = 0; i < ABSTRACT_SOCKET_VARIANTS; i++) { 248a72f6754SMarkus Armbruster if (row->expect_connect[i]) { 249a72f6754SMarkus Armbruster fd = socket_connect(row->client[i], &error_abort); 2504d3a329aSxiaoqiang zhao g_assert_cmpint(fd, >=, 0); 251a72f6754SMarkus Armbruster } else { 252a72f6754SMarkus Armbruster fd = socket_connect(row->client[i], &err); 253a72f6754SMarkus Armbruster g_assert_cmpint(fd, ==, -1); 254a72f6754SMarkus Armbruster error_free_or_abort(&err); 255a72f6754SMarkus Armbruster } 2564d3a329aSxiaoqiang zhao close(fd); 257a72f6754SMarkus Armbruster } 2584d3a329aSxiaoqiang zhao return NULL; 2594d3a329aSxiaoqiang zhao } 2604d3a329aSxiaoqiang zhao 261a72f6754SMarkus Armbruster static void test_socket_unix_abstract_row(abstract_socket_matrix_row *test) 26289cb0bb5SMarkus Armbruster { 263a72f6754SMarkus Armbruster int fd, connfd, i; 26439458d4eSMarkus Armbruster GThread *cli; 26539458d4eSMarkus Armbruster struct sockaddr_un un; 26639458d4eSMarkus Armbruster socklen_t len = sizeof(un); 26789cb0bb5SMarkus Armbruster 268a72f6754SMarkus Armbruster /* Last one must connect, or else accept() below hangs */ 269a72f6754SMarkus Armbruster assert(test->expect_connect[ABSTRACT_SOCKET_VARIANTS - 1]); 270a72f6754SMarkus Armbruster 271a72f6754SMarkus Armbruster fd = socket_listen(test->server, 1, &error_abort); 27239458d4eSMarkus Armbruster g_assert_cmpint(fd, >=, 0); 27339458d4eSMarkus Armbruster g_assert(fd_is_socket(fd)); 27489cb0bb5SMarkus Armbruster 27589cb0bb5SMarkus Armbruster cli = g_thread_new("abstract_unix_client", 27689cb0bb5SMarkus Armbruster unix_client_thread_func, 277a72f6754SMarkus Armbruster test); 27889cb0bb5SMarkus Armbruster 279a72f6754SMarkus Armbruster for (i = 0; i < ABSTRACT_SOCKET_VARIANTS; i++) { 280a72f6754SMarkus Armbruster if (test->expect_connect[i]) { 28139458d4eSMarkus Armbruster connfd = accept(fd, (struct sockaddr *)&un, &len); 28239458d4eSMarkus Armbruster g_assert_cmpint(connfd, !=, -1); 28339458d4eSMarkus Armbruster close(connfd); 284a72f6754SMarkus Armbruster } 285a72f6754SMarkus Armbruster } 28639458d4eSMarkus Armbruster 28739458d4eSMarkus Armbruster close(fd); 28889cb0bb5SMarkus Armbruster g_thread_join(cli); 28989cb0bb5SMarkus Armbruster } 29089cb0bb5SMarkus Armbruster 291a72f6754SMarkus Armbruster static void test_socket_unix_abstract(void) 2924d3a329aSxiaoqiang zhao { 293a72f6754SMarkus Armbruster SocketAddress addr, addr_tight, addr_padded; 294a72f6754SMarkus Armbruster abstract_socket_matrix_row matrix[ABSTRACT_SOCKET_VARIANTS] = { 295a72f6754SMarkus Armbruster { &addr, 296a72f6754SMarkus Armbruster { &addr_tight, &addr_padded, &addr }, 297b08cc97dSMarkus Armbruster { true, false, true } }, 298a72f6754SMarkus Armbruster { &addr_tight, 299a72f6754SMarkus Armbruster { &addr_padded, &addr, &addr_tight }, 300b08cc97dSMarkus Armbruster { false, true, true } }, 301a72f6754SMarkus Armbruster { &addr_padded, 302a72f6754SMarkus Armbruster { &addr, &addr_tight, &addr_padded }, 303b08cc97dSMarkus Armbruster { false, false, true } } 304a72f6754SMarkus Armbruster }; 305a72f6754SMarkus Armbruster int i; 3064d3a329aSxiaoqiang zhao 30758550701SPhilippe Mathieu-Daudé i = g_file_open_tmp("unix-XXXXXX", &addr.u.q_unix.path, NULL); 30858550701SPhilippe Mathieu-Daudé g_assert_true(i >= 0); 30958550701SPhilippe Mathieu-Daudé close(i); 31058550701SPhilippe Mathieu-Daudé 311718a9be0SMarkus Armbruster addr.type = SOCKET_ADDRESS_TYPE_UNIX; 312718a9be0SMarkus Armbruster addr.u.q_unix.has_abstract = true; 313718a9be0SMarkus Armbruster addr.u.q_unix.abstract = true; 314718a9be0SMarkus Armbruster addr.u.q_unix.has_tight = false; 315718a9be0SMarkus Armbruster addr.u.q_unix.tight = false; 3164d3a329aSxiaoqiang zhao 317a72f6754SMarkus Armbruster addr_tight = addr; 318a72f6754SMarkus Armbruster addr_tight.u.q_unix.has_tight = true; 319a72f6754SMarkus Armbruster addr_tight.u.q_unix.tight = true; 320a72f6754SMarkus Armbruster 321a72f6754SMarkus Armbruster addr_padded = addr; 322a72f6754SMarkus Armbruster addr_padded.u.q_unix.has_tight = true; 323a72f6754SMarkus Armbruster addr_padded.u.q_unix.tight = false; 324a72f6754SMarkus Armbruster 325a72f6754SMarkus Armbruster for (i = 0; i < ABSTRACT_SOCKET_VARIANTS; i++) { 326a72f6754SMarkus Armbruster test_socket_unix_abstract_row(&matrix[i]); 327a72f6754SMarkus Armbruster } 3284d3a329aSxiaoqiang zhao 329f0cb6828SThomas Huth unlink(addr.u.q_unix.path); 330718a9be0SMarkus Armbruster g_free(addr.u.q_unix.path); 3314d3a329aSxiaoqiang zhao } 3328acefc79SMarkus Armbruster 3338acefc79SMarkus Armbruster #endif /* CONFIG_LINUX */ 3341723d6b1SDaniel P. Berrange 335316e8ee8SJuraj Marcin static void inet_parse_test_helper(const char *str, 336316e8ee8SJuraj Marcin InetSocketAddress *exp_addr, bool success) 337316e8ee8SJuraj Marcin { 338316e8ee8SJuraj Marcin InetSocketAddress addr; 339316e8ee8SJuraj Marcin Error *error = NULL; 340316e8ee8SJuraj Marcin 341316e8ee8SJuraj Marcin int rc = inet_parse(&addr, str, &error); 342316e8ee8SJuraj Marcin 343316e8ee8SJuraj Marcin if (success) { 344316e8ee8SJuraj Marcin g_assert_cmpint(rc, ==, 0); 345316e8ee8SJuraj Marcin } else { 346316e8ee8SJuraj Marcin g_assert_cmpint(rc, <, 0); 347316e8ee8SJuraj Marcin } 348316e8ee8SJuraj Marcin if (exp_addr != NULL) { 349316e8ee8SJuraj Marcin g_assert_cmpstr(addr.host, ==, exp_addr->host); 350316e8ee8SJuraj Marcin g_assert_cmpstr(addr.port, ==, exp_addr->port); 351316e8ee8SJuraj Marcin /* Own members: */ 352316e8ee8SJuraj Marcin g_assert_cmpint(addr.has_numeric, ==, exp_addr->has_numeric); 353316e8ee8SJuraj Marcin g_assert_cmpint(addr.numeric, ==, exp_addr->numeric); 354316e8ee8SJuraj Marcin g_assert_cmpint(addr.has_to, ==, exp_addr->has_to); 355316e8ee8SJuraj Marcin g_assert_cmpint(addr.to, ==, exp_addr->to); 356316e8ee8SJuraj Marcin g_assert_cmpint(addr.has_ipv4, ==, exp_addr->has_ipv4); 357316e8ee8SJuraj Marcin g_assert_cmpint(addr.ipv4, ==, exp_addr->ipv4); 358316e8ee8SJuraj Marcin g_assert_cmpint(addr.has_ipv6, ==, exp_addr->has_ipv6); 359316e8ee8SJuraj Marcin g_assert_cmpint(addr.ipv6, ==, exp_addr->ipv6); 360316e8ee8SJuraj Marcin g_assert_cmpint(addr.has_keep_alive, ==, exp_addr->has_keep_alive); 361316e8ee8SJuraj Marcin g_assert_cmpint(addr.keep_alive, ==, exp_addr->keep_alive); 362*1bd4237cSJuraj Marcin #ifdef HAVE_TCP_KEEPCNT 363*1bd4237cSJuraj Marcin g_assert_cmpint(addr.has_keep_alive_count, ==, 364*1bd4237cSJuraj Marcin exp_addr->has_keep_alive_count); 365*1bd4237cSJuraj Marcin g_assert_cmpint(addr.keep_alive_count, ==, 366*1bd4237cSJuraj Marcin exp_addr->keep_alive_count); 367*1bd4237cSJuraj Marcin #endif 368*1bd4237cSJuraj Marcin #ifdef HAVE_TCP_KEEPIDLE 369*1bd4237cSJuraj Marcin g_assert_cmpint(addr.has_keep_alive_idle, ==, 370*1bd4237cSJuraj Marcin exp_addr->has_keep_alive_idle); 371*1bd4237cSJuraj Marcin g_assert_cmpint(addr.keep_alive_idle, ==, 372*1bd4237cSJuraj Marcin exp_addr->keep_alive_idle); 373*1bd4237cSJuraj Marcin #endif 374*1bd4237cSJuraj Marcin #ifdef HAVE_TCP_KEEPINTVL 375*1bd4237cSJuraj Marcin g_assert_cmpint(addr.has_keep_alive_interval, ==, 376*1bd4237cSJuraj Marcin exp_addr->has_keep_alive_interval); 377*1bd4237cSJuraj Marcin g_assert_cmpint(addr.keep_alive_interval, ==, 378*1bd4237cSJuraj Marcin exp_addr->keep_alive_interval); 379*1bd4237cSJuraj Marcin #endif 380316e8ee8SJuraj Marcin #ifdef HAVE_IPPROTO_MPTCP 381316e8ee8SJuraj Marcin g_assert_cmpint(addr.has_mptcp, ==, exp_addr->has_mptcp); 382316e8ee8SJuraj Marcin g_assert_cmpint(addr.mptcp, ==, exp_addr->mptcp); 383316e8ee8SJuraj Marcin #endif 384316e8ee8SJuraj Marcin } 385316e8ee8SJuraj Marcin 386316e8ee8SJuraj Marcin g_free(addr.host); 387316e8ee8SJuraj Marcin g_free(addr.port); 388316e8ee8SJuraj Marcin } 389316e8ee8SJuraj Marcin 390316e8ee8SJuraj Marcin static void test_inet_parse_nohost_good(void) 391316e8ee8SJuraj Marcin { 392316e8ee8SJuraj Marcin char host[] = ""; 393316e8ee8SJuraj Marcin char port[] = "5000"; 394316e8ee8SJuraj Marcin InetSocketAddress exp_addr = { 395316e8ee8SJuraj Marcin .host = host, 396316e8ee8SJuraj Marcin .port = port, 397316e8ee8SJuraj Marcin }; 398316e8ee8SJuraj Marcin inet_parse_test_helper(":5000", &exp_addr, true); 399316e8ee8SJuraj Marcin } 400316e8ee8SJuraj Marcin 401316e8ee8SJuraj Marcin static void test_inet_parse_empty_bad(void) 402316e8ee8SJuraj Marcin { 403316e8ee8SJuraj Marcin inet_parse_test_helper("", NULL, false); 404316e8ee8SJuraj Marcin } 405316e8ee8SJuraj Marcin 406316e8ee8SJuraj Marcin static void test_inet_parse_only_colon_bad(void) 407316e8ee8SJuraj Marcin { 408316e8ee8SJuraj Marcin inet_parse_test_helper(":", NULL, false); 409316e8ee8SJuraj Marcin } 410316e8ee8SJuraj Marcin 411316e8ee8SJuraj Marcin static void test_inet_parse_ipv4_good(void) 412316e8ee8SJuraj Marcin { 413316e8ee8SJuraj Marcin char host[] = "127.0.0.1"; 414316e8ee8SJuraj Marcin char port[] = "5000"; 415316e8ee8SJuraj Marcin InetSocketAddress exp_addr = { 416316e8ee8SJuraj Marcin .host = host, 417316e8ee8SJuraj Marcin .port = port, 418316e8ee8SJuraj Marcin }; 419316e8ee8SJuraj Marcin inet_parse_test_helper("127.0.0.1:5000", &exp_addr, true); 420316e8ee8SJuraj Marcin } 421316e8ee8SJuraj Marcin 422316e8ee8SJuraj Marcin static void test_inet_parse_ipv4_noport_bad(void) 423316e8ee8SJuraj Marcin { 424316e8ee8SJuraj Marcin inet_parse_test_helper("127.0.0.1", NULL, false); 425316e8ee8SJuraj Marcin } 426316e8ee8SJuraj Marcin 427316e8ee8SJuraj Marcin static void test_inet_parse_ipv6_good(void) 428316e8ee8SJuraj Marcin { 429316e8ee8SJuraj Marcin char host[] = "::1"; 430316e8ee8SJuraj Marcin char port[] = "5000"; 431316e8ee8SJuraj Marcin InetSocketAddress exp_addr = { 432316e8ee8SJuraj Marcin .host = host, 433316e8ee8SJuraj Marcin .port = port, 434316e8ee8SJuraj Marcin }; 435316e8ee8SJuraj Marcin inet_parse_test_helper("[::1]:5000", &exp_addr, true); 436316e8ee8SJuraj Marcin } 437316e8ee8SJuraj Marcin 438316e8ee8SJuraj Marcin static void test_inet_parse_ipv6_noend_bad(void) 439316e8ee8SJuraj Marcin { 440316e8ee8SJuraj Marcin inet_parse_test_helper("[::1", NULL, false); 441316e8ee8SJuraj Marcin } 442316e8ee8SJuraj Marcin 443316e8ee8SJuraj Marcin static void test_inet_parse_ipv6_noport_bad(void) 444316e8ee8SJuraj Marcin { 445316e8ee8SJuraj Marcin inet_parse_test_helper("[::1]:", NULL, false); 446316e8ee8SJuraj Marcin } 447316e8ee8SJuraj Marcin 448316e8ee8SJuraj Marcin static void test_inet_parse_ipv6_empty_bad(void) 449316e8ee8SJuraj Marcin { 450316e8ee8SJuraj Marcin inet_parse_test_helper("[]:5000", NULL, false); 451316e8ee8SJuraj Marcin } 452316e8ee8SJuraj Marcin 453316e8ee8SJuraj Marcin static void test_inet_parse_hostname_good(void) 454316e8ee8SJuraj Marcin { 455316e8ee8SJuraj Marcin char host[] = "localhost"; 456316e8ee8SJuraj Marcin char port[] = "5000"; 457316e8ee8SJuraj Marcin InetSocketAddress exp_addr = { 458316e8ee8SJuraj Marcin .host = host, 459316e8ee8SJuraj Marcin .port = port, 460316e8ee8SJuraj Marcin }; 461316e8ee8SJuraj Marcin inet_parse_test_helper("localhost:5000", &exp_addr, true); 462316e8ee8SJuraj Marcin } 463316e8ee8SJuraj Marcin 464316e8ee8SJuraj Marcin static void test_inet_parse_all_options_good(void) 465316e8ee8SJuraj Marcin { 466316e8ee8SJuraj Marcin char host[] = "::1"; 467316e8ee8SJuraj Marcin char port[] = "5000"; 468316e8ee8SJuraj Marcin InetSocketAddress exp_addr = { 469316e8ee8SJuraj Marcin .host = host, 470316e8ee8SJuraj Marcin .port = port, 471316e8ee8SJuraj Marcin .has_numeric = true, 472316e8ee8SJuraj Marcin .numeric = true, 473316e8ee8SJuraj Marcin .has_to = true, 474316e8ee8SJuraj Marcin .to = 5006, 475316e8ee8SJuraj Marcin .has_ipv4 = true, 476316e8ee8SJuraj Marcin .ipv4 = false, 477316e8ee8SJuraj Marcin .has_ipv6 = true, 478316e8ee8SJuraj Marcin .ipv6 = true, 479316e8ee8SJuraj Marcin .has_keep_alive = true, 480316e8ee8SJuraj Marcin .keep_alive = true, 481*1bd4237cSJuraj Marcin #ifdef HAVE_TCP_KEEPCNT 482*1bd4237cSJuraj Marcin .has_keep_alive_count = true, 483*1bd4237cSJuraj Marcin .keep_alive_count = 10, 484*1bd4237cSJuraj Marcin #endif 485*1bd4237cSJuraj Marcin #ifdef HAVE_TCP_KEEPIDLE 486*1bd4237cSJuraj Marcin .has_keep_alive_idle = true, 487*1bd4237cSJuraj Marcin .keep_alive_idle = 60, 488*1bd4237cSJuraj Marcin #endif 489*1bd4237cSJuraj Marcin #ifdef HAVE_TCP_KEEPINTVL 490*1bd4237cSJuraj Marcin .has_keep_alive_interval = true, 491*1bd4237cSJuraj Marcin .keep_alive_interval = 30, 492*1bd4237cSJuraj Marcin #endif 493316e8ee8SJuraj Marcin #ifdef HAVE_IPPROTO_MPTCP 494316e8ee8SJuraj Marcin .has_mptcp = true, 495316e8ee8SJuraj Marcin .mptcp = false, 496316e8ee8SJuraj Marcin #endif 497316e8ee8SJuraj Marcin }; 498316e8ee8SJuraj Marcin inet_parse_test_helper( 499316e8ee8SJuraj Marcin "[::1]:5000,numeric=on,to=5006,ipv4=off,ipv6=on,keep-alive=on" 500*1bd4237cSJuraj Marcin #ifdef HAVE_TCP_KEEPCNT 501*1bd4237cSJuraj Marcin ",keep-alive-count=10" 502*1bd4237cSJuraj Marcin #endif 503*1bd4237cSJuraj Marcin #ifdef HAVE_TCP_KEEPIDLE 504*1bd4237cSJuraj Marcin ",keep-alive-idle=60" 505*1bd4237cSJuraj Marcin #endif 506*1bd4237cSJuraj Marcin #ifdef HAVE_TCP_KEEPINTVL 507*1bd4237cSJuraj Marcin ",keep-alive-interval=30" 508*1bd4237cSJuraj Marcin #endif 509316e8ee8SJuraj Marcin #ifdef HAVE_IPPROTO_MPTCP 510316e8ee8SJuraj Marcin ",mptcp=off" 511316e8ee8SJuraj Marcin #endif 512316e8ee8SJuraj Marcin , &exp_addr, true); 513316e8ee8SJuraj Marcin } 514316e8ee8SJuraj Marcin 515316e8ee8SJuraj Marcin static void test_inet_parse_all_implicit_bool_good(void) 516316e8ee8SJuraj Marcin { 517316e8ee8SJuraj Marcin char host[] = "::1"; 518316e8ee8SJuraj Marcin char port[] = "5000"; 519316e8ee8SJuraj Marcin InetSocketAddress exp_addr = { 520316e8ee8SJuraj Marcin .host = host, 521316e8ee8SJuraj Marcin .port = port, 522316e8ee8SJuraj Marcin .has_numeric = true, 523316e8ee8SJuraj Marcin .numeric = true, 524316e8ee8SJuraj Marcin .has_to = true, 525316e8ee8SJuraj Marcin .to = 5006, 526316e8ee8SJuraj Marcin .has_ipv4 = true, 527316e8ee8SJuraj Marcin .ipv4 = true, 528316e8ee8SJuraj Marcin .has_ipv6 = true, 529316e8ee8SJuraj Marcin .ipv6 = true, 530316e8ee8SJuraj Marcin .has_keep_alive = true, 531316e8ee8SJuraj Marcin .keep_alive = true, 532316e8ee8SJuraj Marcin #ifdef HAVE_IPPROTO_MPTCP 533316e8ee8SJuraj Marcin .has_mptcp = true, 534316e8ee8SJuraj Marcin .mptcp = true, 535316e8ee8SJuraj Marcin #endif 536316e8ee8SJuraj Marcin }; 537316e8ee8SJuraj Marcin inet_parse_test_helper( 538316e8ee8SJuraj Marcin "[::1]:5000,numeric,to=5006,ipv4,ipv6,keep-alive" 539316e8ee8SJuraj Marcin #ifdef HAVE_IPPROTO_MPTCP 540316e8ee8SJuraj Marcin ",mptcp" 541316e8ee8SJuraj Marcin #endif 542316e8ee8SJuraj Marcin , &exp_addr, true); 543316e8ee8SJuraj Marcin } 544316e8ee8SJuraj Marcin 54558dc31f1SDaniel P. Berrange int main(int argc, char **argv) 54658dc31f1SDaniel P. Berrange { 54758dc31f1SDaniel P. Berrange bool has_ipv4, has_ipv6; 54858dc31f1SDaniel P. Berrange 5498330bd53SYonggang Luo qemu_init_main_loop(&error_abort); 55058dc31f1SDaniel P. Berrange socket_init(); 55158dc31f1SDaniel P. Berrange 55258dc31f1SDaniel P. Berrange g_test_init(&argc, &argv, NULL); 55358dc31f1SDaniel P. Berrange 55458dc31f1SDaniel P. Berrange /* We're creating actual IPv4/6 sockets, so we should 55558dc31f1SDaniel P. Berrange * check if the host running tests actually supports 55658dc31f1SDaniel P. Berrange * each protocol to avoid breaking tests on machines 55758dc31f1SDaniel P. Berrange * with either IPv4 or IPv6 disabled. 55858dc31f1SDaniel P. Berrange */ 55958dc31f1SDaniel P. Berrange if (socket_check_protocol_support(&has_ipv4, &has_ipv6) < 0) { 560a4eb74a6SMarc-André Lureau g_printerr("socket_check_protocol_support() failed\n"); 561a4eb74a6SMarc-André Lureau goto end; 56258dc31f1SDaniel P. Berrange } 56358dc31f1SDaniel P. Berrange 56458dc31f1SDaniel P. Berrange if (has_ipv4) { 56558dc31f1SDaniel P. Berrange g_test_add_func("/util/socket/is-socket/bad", 56658dc31f1SDaniel P. Berrange test_fd_is_socket_bad); 56758dc31f1SDaniel P. Berrange g_test_add_func("/util/socket/is-socket/good", 56858dc31f1SDaniel P. Berrange test_fd_is_socket_good); 5698330bd53SYonggang Luo #ifndef _WIN32 5701723d6b1SDaniel P. Berrange g_test_add_func("/socket/fd-pass/name/good", 5711723d6b1SDaniel P. Berrange test_socket_fd_pass_name_good); 5721723d6b1SDaniel P. Berrange g_test_add_func("/socket/fd-pass/name/bad", 5731723d6b1SDaniel P. Berrange test_socket_fd_pass_name_bad); 5741723d6b1SDaniel P. Berrange g_test_add_func("/socket/fd-pass/name/nomon", 5751723d6b1SDaniel P. Berrange test_socket_fd_pass_name_nomon); 5761723d6b1SDaniel P. Berrange g_test_add_func("/socket/fd-pass/num/good", 5771723d6b1SDaniel P. Berrange test_socket_fd_pass_num_good); 5781723d6b1SDaniel P. Berrange g_test_add_func("/socket/fd-pass/num/bad", 5791723d6b1SDaniel P. Berrange test_socket_fd_pass_num_bad); 5801723d6b1SDaniel P. Berrange g_test_add_func("/socket/fd-pass/num/nocli", 5811723d6b1SDaniel P. Berrange test_socket_fd_pass_num_nocli); 5828330bd53SYonggang Luo #endif 58358dc31f1SDaniel P. Berrange } 58458dc31f1SDaniel P. Berrange 5858acefc79SMarkus Armbruster #ifdef CONFIG_LINUX 586a72f6754SMarkus Armbruster g_test_add_func("/util/socket/unix-abstract", 587a72f6754SMarkus Armbruster test_socket_unix_abstract); 5884d3a329aSxiaoqiang zhao #endif 5894d3a329aSxiaoqiang zhao 590316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/nohost-good", 591316e8ee8SJuraj Marcin test_inet_parse_nohost_good); 592316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/empty-bad", 593316e8ee8SJuraj Marcin test_inet_parse_empty_bad); 594316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/only-colon-bad", 595316e8ee8SJuraj Marcin test_inet_parse_only_colon_bad); 596316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/ipv4-good", 597316e8ee8SJuraj Marcin test_inet_parse_ipv4_good); 598316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/ipv4-noport-bad", 599316e8ee8SJuraj Marcin test_inet_parse_ipv4_noport_bad); 600316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/ipv6-good", 601316e8ee8SJuraj Marcin test_inet_parse_ipv6_good); 602316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/ipv6-noend-bad", 603316e8ee8SJuraj Marcin test_inet_parse_ipv6_noend_bad); 604316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/ipv6-noport-bad", 605316e8ee8SJuraj Marcin test_inet_parse_ipv6_noport_bad); 606316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/ipv6-empty-bad", 607316e8ee8SJuraj Marcin test_inet_parse_ipv6_empty_bad); 608316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/hostname-good", 609316e8ee8SJuraj Marcin test_inet_parse_hostname_good); 610316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/all-options-good", 611316e8ee8SJuraj Marcin test_inet_parse_all_options_good); 612316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/all-bare-bool-good", 613316e8ee8SJuraj Marcin test_inet_parse_all_implicit_bool_good); 614316e8ee8SJuraj Marcin 615a4eb74a6SMarc-André Lureau end: 61658dc31f1SDaniel P. Berrange return g_test_run(); 61758dc31f1SDaniel P. Berrange } 618