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
test_fd_is_socket_bad(void)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
test_fd_is_socket_good(void)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
monitor_get_fd(Monitor * mon,const char * fdname,Error ** errp)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 */
monitor_cur(void)74947e4744SKevin Wolf Monitor *monitor_cur(void) { return cur_mon; }
monitor_set_cur(Coroutine * co,Monitor * mon)75130d4824SMarkus Armbruster Monitor *monitor_set_cur(Coroutine *co, Monitor *mon) { abort(); }
monitor_vprintf(Monitor * mon,const char * fmt,va_list ap)76637de4dbSMarkus Armbruster int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); }
7730bdb3c5SDaniel P. Berrange
788330bd53SYonggang Luo #ifndef _WIN32
test_socket_fd_pass_name_good(void)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
test_socket_fd_pass_name_bad(void)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
test_socket_fd_pass_name_nomon(void)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
test_socket_fd_pass_num_good(void)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
test_socket_fd_pass_num_bad(void)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
test_socket_fd_pass_num_nocli(void)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
unix_client_thread_func(gpointer user_data)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
test_socket_unix_abstract_row(abstract_socket_matrix_row * test)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
test_socket_unix_abstract(void)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
inet_parse_test_helper(const char * str,InetSocketAddress * exp_addr,bool success)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) {
344*5c54a367SMatheus Tavares Bernardino if (error) {
345*5c54a367SMatheus Tavares Bernardino error_report_err(error);
346*5c54a367SMatheus Tavares Bernardino }
347316e8ee8SJuraj Marcin g_assert_cmpint(rc, ==, 0);
348316e8ee8SJuraj Marcin } else {
349*5c54a367SMatheus Tavares Bernardino error_free(error);
350316e8ee8SJuraj Marcin g_assert_cmpint(rc, <, 0);
351316e8ee8SJuraj Marcin }
352316e8ee8SJuraj Marcin if (exp_addr != NULL) {
353316e8ee8SJuraj Marcin g_assert_cmpstr(addr.host, ==, exp_addr->host);
354316e8ee8SJuraj Marcin g_assert_cmpstr(addr.port, ==, exp_addr->port);
355316e8ee8SJuraj Marcin /* Own members: */
356316e8ee8SJuraj Marcin g_assert_cmpint(addr.has_numeric, ==, exp_addr->has_numeric);
357316e8ee8SJuraj Marcin g_assert_cmpint(addr.numeric, ==, exp_addr->numeric);
358316e8ee8SJuraj Marcin g_assert_cmpint(addr.has_to, ==, exp_addr->has_to);
359316e8ee8SJuraj Marcin g_assert_cmpint(addr.to, ==, exp_addr->to);
360316e8ee8SJuraj Marcin g_assert_cmpint(addr.has_ipv4, ==, exp_addr->has_ipv4);
361316e8ee8SJuraj Marcin g_assert_cmpint(addr.ipv4, ==, exp_addr->ipv4);
362316e8ee8SJuraj Marcin g_assert_cmpint(addr.has_ipv6, ==, exp_addr->has_ipv6);
363316e8ee8SJuraj Marcin g_assert_cmpint(addr.ipv6, ==, exp_addr->ipv6);
364316e8ee8SJuraj Marcin g_assert_cmpint(addr.has_keep_alive, ==, exp_addr->has_keep_alive);
365316e8ee8SJuraj Marcin g_assert_cmpint(addr.keep_alive, ==, exp_addr->keep_alive);
3661bd4237cSJuraj Marcin #ifdef HAVE_TCP_KEEPCNT
3671bd4237cSJuraj Marcin g_assert_cmpint(addr.has_keep_alive_count, ==,
3681bd4237cSJuraj Marcin exp_addr->has_keep_alive_count);
3691bd4237cSJuraj Marcin g_assert_cmpint(addr.keep_alive_count, ==,
3701bd4237cSJuraj Marcin exp_addr->keep_alive_count);
3711bd4237cSJuraj Marcin #endif
3721bd4237cSJuraj Marcin #ifdef HAVE_TCP_KEEPIDLE
3731bd4237cSJuraj Marcin g_assert_cmpint(addr.has_keep_alive_idle, ==,
3741bd4237cSJuraj Marcin exp_addr->has_keep_alive_idle);
3751bd4237cSJuraj Marcin g_assert_cmpint(addr.keep_alive_idle, ==,
3761bd4237cSJuraj Marcin exp_addr->keep_alive_idle);
3771bd4237cSJuraj Marcin #endif
3781bd4237cSJuraj Marcin #ifdef HAVE_TCP_KEEPINTVL
3791bd4237cSJuraj Marcin g_assert_cmpint(addr.has_keep_alive_interval, ==,
3801bd4237cSJuraj Marcin exp_addr->has_keep_alive_interval);
3811bd4237cSJuraj Marcin g_assert_cmpint(addr.keep_alive_interval, ==,
3821bd4237cSJuraj Marcin exp_addr->keep_alive_interval);
3831bd4237cSJuraj Marcin #endif
384316e8ee8SJuraj Marcin #ifdef HAVE_IPPROTO_MPTCP
385316e8ee8SJuraj Marcin g_assert_cmpint(addr.has_mptcp, ==, exp_addr->has_mptcp);
386316e8ee8SJuraj Marcin g_assert_cmpint(addr.mptcp, ==, exp_addr->mptcp);
387316e8ee8SJuraj Marcin #endif
388316e8ee8SJuraj Marcin }
389316e8ee8SJuraj Marcin
390316e8ee8SJuraj Marcin g_free(addr.host);
391316e8ee8SJuraj Marcin g_free(addr.port);
392316e8ee8SJuraj Marcin }
393316e8ee8SJuraj Marcin
test_inet_parse_nohost_good(void)394316e8ee8SJuraj Marcin static void test_inet_parse_nohost_good(void)
395316e8ee8SJuraj Marcin {
396316e8ee8SJuraj Marcin char host[] = "";
397316e8ee8SJuraj Marcin char port[] = "5000";
398316e8ee8SJuraj Marcin InetSocketAddress exp_addr = {
399316e8ee8SJuraj Marcin .host = host,
400316e8ee8SJuraj Marcin .port = port,
401316e8ee8SJuraj Marcin };
402316e8ee8SJuraj Marcin inet_parse_test_helper(":5000", &exp_addr, true);
403316e8ee8SJuraj Marcin }
404316e8ee8SJuraj Marcin
test_inet_parse_empty_bad(void)405316e8ee8SJuraj Marcin static void test_inet_parse_empty_bad(void)
406316e8ee8SJuraj Marcin {
407316e8ee8SJuraj Marcin inet_parse_test_helper("", NULL, false);
408316e8ee8SJuraj Marcin }
409316e8ee8SJuraj Marcin
test_inet_parse_only_colon_bad(void)410316e8ee8SJuraj Marcin static void test_inet_parse_only_colon_bad(void)
411316e8ee8SJuraj Marcin {
412316e8ee8SJuraj Marcin inet_parse_test_helper(":", NULL, false);
413316e8ee8SJuraj Marcin }
414316e8ee8SJuraj Marcin
test_inet_parse_ipv4_good(void)415316e8ee8SJuraj Marcin static void test_inet_parse_ipv4_good(void)
416316e8ee8SJuraj Marcin {
417316e8ee8SJuraj Marcin char host[] = "127.0.0.1";
418316e8ee8SJuraj Marcin char port[] = "5000";
419316e8ee8SJuraj Marcin InetSocketAddress exp_addr = {
420316e8ee8SJuraj Marcin .host = host,
421316e8ee8SJuraj Marcin .port = port,
422316e8ee8SJuraj Marcin };
423316e8ee8SJuraj Marcin inet_parse_test_helper("127.0.0.1:5000", &exp_addr, true);
424316e8ee8SJuraj Marcin }
425316e8ee8SJuraj Marcin
test_inet_parse_ipv4_noport_bad(void)426316e8ee8SJuraj Marcin static void test_inet_parse_ipv4_noport_bad(void)
427316e8ee8SJuraj Marcin {
428316e8ee8SJuraj Marcin inet_parse_test_helper("127.0.0.1", NULL, false);
429316e8ee8SJuraj Marcin }
430316e8ee8SJuraj Marcin
test_inet_parse_ipv6_good(void)431316e8ee8SJuraj Marcin static void test_inet_parse_ipv6_good(void)
432316e8ee8SJuraj Marcin {
433316e8ee8SJuraj Marcin char host[] = "::1";
434316e8ee8SJuraj Marcin char port[] = "5000";
435316e8ee8SJuraj Marcin InetSocketAddress exp_addr = {
436316e8ee8SJuraj Marcin .host = host,
437316e8ee8SJuraj Marcin .port = port,
438316e8ee8SJuraj Marcin };
439316e8ee8SJuraj Marcin inet_parse_test_helper("[::1]:5000", &exp_addr, true);
440316e8ee8SJuraj Marcin }
441316e8ee8SJuraj Marcin
test_inet_parse_ipv6_noend_bad(void)442316e8ee8SJuraj Marcin static void test_inet_parse_ipv6_noend_bad(void)
443316e8ee8SJuraj Marcin {
444316e8ee8SJuraj Marcin inet_parse_test_helper("[::1", NULL, false);
445316e8ee8SJuraj Marcin }
446316e8ee8SJuraj Marcin
test_inet_parse_ipv6_noport_bad(void)447316e8ee8SJuraj Marcin static void test_inet_parse_ipv6_noport_bad(void)
448316e8ee8SJuraj Marcin {
449316e8ee8SJuraj Marcin inet_parse_test_helper("[::1]:", NULL, false);
450316e8ee8SJuraj Marcin }
451316e8ee8SJuraj Marcin
test_inet_parse_ipv6_empty_bad(void)452316e8ee8SJuraj Marcin static void test_inet_parse_ipv6_empty_bad(void)
453316e8ee8SJuraj Marcin {
454316e8ee8SJuraj Marcin inet_parse_test_helper("[]:5000", NULL, false);
455316e8ee8SJuraj Marcin }
456316e8ee8SJuraj Marcin
test_inet_parse_hostname_good(void)457316e8ee8SJuraj Marcin static void test_inet_parse_hostname_good(void)
458316e8ee8SJuraj Marcin {
459316e8ee8SJuraj Marcin char host[] = "localhost";
460316e8ee8SJuraj Marcin char port[] = "5000";
461316e8ee8SJuraj Marcin InetSocketAddress exp_addr = {
462316e8ee8SJuraj Marcin .host = host,
463316e8ee8SJuraj Marcin .port = port,
464316e8ee8SJuraj Marcin };
465316e8ee8SJuraj Marcin inet_parse_test_helper("localhost:5000", &exp_addr, true);
466316e8ee8SJuraj Marcin }
467316e8ee8SJuraj Marcin
test_inet_parse_all_options_good(void)468316e8ee8SJuraj Marcin static void test_inet_parse_all_options_good(void)
469316e8ee8SJuraj Marcin {
470316e8ee8SJuraj Marcin char host[] = "::1";
471316e8ee8SJuraj Marcin char port[] = "5000";
472316e8ee8SJuraj Marcin InetSocketAddress exp_addr = {
473316e8ee8SJuraj Marcin .host = host,
474316e8ee8SJuraj Marcin .port = port,
475316e8ee8SJuraj Marcin .has_numeric = true,
476316e8ee8SJuraj Marcin .numeric = true,
477316e8ee8SJuraj Marcin .has_to = true,
478316e8ee8SJuraj Marcin .to = 5006,
479316e8ee8SJuraj Marcin .has_ipv4 = true,
480316e8ee8SJuraj Marcin .ipv4 = false,
481316e8ee8SJuraj Marcin .has_ipv6 = true,
482316e8ee8SJuraj Marcin .ipv6 = true,
483316e8ee8SJuraj Marcin .has_keep_alive = true,
484316e8ee8SJuraj Marcin .keep_alive = true,
4851bd4237cSJuraj Marcin #ifdef HAVE_TCP_KEEPCNT
4861bd4237cSJuraj Marcin .has_keep_alive_count = true,
4871bd4237cSJuraj Marcin .keep_alive_count = 10,
4881bd4237cSJuraj Marcin #endif
4891bd4237cSJuraj Marcin #ifdef HAVE_TCP_KEEPIDLE
4901bd4237cSJuraj Marcin .has_keep_alive_idle = true,
4911bd4237cSJuraj Marcin .keep_alive_idle = 60,
4921bd4237cSJuraj Marcin #endif
4931bd4237cSJuraj Marcin #ifdef HAVE_TCP_KEEPINTVL
4941bd4237cSJuraj Marcin .has_keep_alive_interval = true,
4951bd4237cSJuraj Marcin .keep_alive_interval = 30,
4961bd4237cSJuraj Marcin #endif
497316e8ee8SJuraj Marcin #ifdef HAVE_IPPROTO_MPTCP
498316e8ee8SJuraj Marcin .has_mptcp = true,
499316e8ee8SJuraj Marcin .mptcp = false,
500316e8ee8SJuraj Marcin #endif
501316e8ee8SJuraj Marcin };
502316e8ee8SJuraj Marcin inet_parse_test_helper(
503316e8ee8SJuraj Marcin "[::1]:5000,numeric=on,to=5006,ipv4=off,ipv6=on,keep-alive=on"
5041bd4237cSJuraj Marcin #ifdef HAVE_TCP_KEEPCNT
5051bd4237cSJuraj Marcin ",keep-alive-count=10"
5061bd4237cSJuraj Marcin #endif
5071bd4237cSJuraj Marcin #ifdef HAVE_TCP_KEEPIDLE
5081bd4237cSJuraj Marcin ",keep-alive-idle=60"
5091bd4237cSJuraj Marcin #endif
5101bd4237cSJuraj Marcin #ifdef HAVE_TCP_KEEPINTVL
5111bd4237cSJuraj Marcin ",keep-alive-interval=30"
5121bd4237cSJuraj Marcin #endif
513316e8ee8SJuraj Marcin #ifdef HAVE_IPPROTO_MPTCP
514316e8ee8SJuraj Marcin ",mptcp=off"
515316e8ee8SJuraj Marcin #endif
516316e8ee8SJuraj Marcin , &exp_addr, true);
517316e8ee8SJuraj Marcin }
518316e8ee8SJuraj Marcin
test_inet_parse_all_implicit_bool_good(void)519316e8ee8SJuraj Marcin static void test_inet_parse_all_implicit_bool_good(void)
520316e8ee8SJuraj Marcin {
521316e8ee8SJuraj Marcin char host[] = "::1";
522316e8ee8SJuraj Marcin char port[] = "5000";
523316e8ee8SJuraj Marcin InetSocketAddress exp_addr = {
524316e8ee8SJuraj Marcin .host = host,
525316e8ee8SJuraj Marcin .port = port,
526316e8ee8SJuraj Marcin .has_numeric = true,
527316e8ee8SJuraj Marcin .numeric = true,
528316e8ee8SJuraj Marcin .has_to = true,
529316e8ee8SJuraj Marcin .to = 5006,
530316e8ee8SJuraj Marcin .has_ipv4 = true,
531316e8ee8SJuraj Marcin .ipv4 = true,
532316e8ee8SJuraj Marcin .has_ipv6 = true,
533316e8ee8SJuraj Marcin .ipv6 = true,
534316e8ee8SJuraj Marcin .has_keep_alive = true,
535316e8ee8SJuraj Marcin .keep_alive = true,
536316e8ee8SJuraj Marcin #ifdef HAVE_IPPROTO_MPTCP
537316e8ee8SJuraj Marcin .has_mptcp = true,
538316e8ee8SJuraj Marcin .mptcp = true,
539316e8ee8SJuraj Marcin #endif
540316e8ee8SJuraj Marcin };
541316e8ee8SJuraj Marcin inet_parse_test_helper(
542316e8ee8SJuraj Marcin "[::1]:5000,numeric,to=5006,ipv4,ipv6,keep-alive"
543316e8ee8SJuraj Marcin #ifdef HAVE_IPPROTO_MPTCP
544316e8ee8SJuraj Marcin ",mptcp"
545316e8ee8SJuraj Marcin #endif
546316e8ee8SJuraj Marcin , &exp_addr, true);
547316e8ee8SJuraj Marcin }
548316e8ee8SJuraj Marcin
main(int argc,char ** argv)54958dc31f1SDaniel P. Berrange int main(int argc, char **argv)
55058dc31f1SDaniel P. Berrange {
55158dc31f1SDaniel P. Berrange bool has_ipv4, has_ipv6;
55258dc31f1SDaniel P. Berrange
5538330bd53SYonggang Luo qemu_init_main_loop(&error_abort);
55458dc31f1SDaniel P. Berrange socket_init();
55558dc31f1SDaniel P. Berrange
55658dc31f1SDaniel P. Berrange g_test_init(&argc, &argv, NULL);
55758dc31f1SDaniel P. Berrange
55858dc31f1SDaniel P. Berrange /* We're creating actual IPv4/6 sockets, so we should
55958dc31f1SDaniel P. Berrange * check if the host running tests actually supports
56058dc31f1SDaniel P. Berrange * each protocol to avoid breaking tests on machines
56158dc31f1SDaniel P. Berrange * with either IPv4 or IPv6 disabled.
56258dc31f1SDaniel P. Berrange */
56358dc31f1SDaniel P. Berrange if (socket_check_protocol_support(&has_ipv4, &has_ipv6) < 0) {
564a4eb74a6SMarc-André Lureau g_printerr("socket_check_protocol_support() failed\n");
565a4eb74a6SMarc-André Lureau goto end;
56658dc31f1SDaniel P. Berrange }
56758dc31f1SDaniel P. Berrange
56858dc31f1SDaniel P. Berrange if (has_ipv4) {
56958dc31f1SDaniel P. Berrange g_test_add_func("/util/socket/is-socket/bad",
57058dc31f1SDaniel P. Berrange test_fd_is_socket_bad);
57158dc31f1SDaniel P. Berrange g_test_add_func("/util/socket/is-socket/good",
57258dc31f1SDaniel P. Berrange test_fd_is_socket_good);
5738330bd53SYonggang Luo #ifndef _WIN32
5741723d6b1SDaniel P. Berrange g_test_add_func("/socket/fd-pass/name/good",
5751723d6b1SDaniel P. Berrange test_socket_fd_pass_name_good);
5761723d6b1SDaniel P. Berrange g_test_add_func("/socket/fd-pass/name/bad",
5771723d6b1SDaniel P. Berrange test_socket_fd_pass_name_bad);
5781723d6b1SDaniel P. Berrange g_test_add_func("/socket/fd-pass/name/nomon",
5791723d6b1SDaniel P. Berrange test_socket_fd_pass_name_nomon);
5801723d6b1SDaniel P. Berrange g_test_add_func("/socket/fd-pass/num/good",
5811723d6b1SDaniel P. Berrange test_socket_fd_pass_num_good);
5821723d6b1SDaniel P. Berrange g_test_add_func("/socket/fd-pass/num/bad",
5831723d6b1SDaniel P. Berrange test_socket_fd_pass_num_bad);
5841723d6b1SDaniel P. Berrange g_test_add_func("/socket/fd-pass/num/nocli",
5851723d6b1SDaniel P. Berrange test_socket_fd_pass_num_nocli);
5868330bd53SYonggang Luo #endif
58758dc31f1SDaniel P. Berrange }
58858dc31f1SDaniel P. Berrange
5898acefc79SMarkus Armbruster #ifdef CONFIG_LINUX
590a72f6754SMarkus Armbruster g_test_add_func("/util/socket/unix-abstract",
591a72f6754SMarkus Armbruster test_socket_unix_abstract);
5924d3a329aSxiaoqiang zhao #endif
5934d3a329aSxiaoqiang zhao
594316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/nohost-good",
595316e8ee8SJuraj Marcin test_inet_parse_nohost_good);
596316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/empty-bad",
597316e8ee8SJuraj Marcin test_inet_parse_empty_bad);
598316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/only-colon-bad",
599316e8ee8SJuraj Marcin test_inet_parse_only_colon_bad);
600316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/ipv4-good",
601316e8ee8SJuraj Marcin test_inet_parse_ipv4_good);
602316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/ipv4-noport-bad",
603316e8ee8SJuraj Marcin test_inet_parse_ipv4_noport_bad);
604316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/ipv6-good",
605316e8ee8SJuraj Marcin test_inet_parse_ipv6_good);
606316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/ipv6-noend-bad",
607316e8ee8SJuraj Marcin test_inet_parse_ipv6_noend_bad);
608316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/ipv6-noport-bad",
609316e8ee8SJuraj Marcin test_inet_parse_ipv6_noport_bad);
610316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/ipv6-empty-bad",
611316e8ee8SJuraj Marcin test_inet_parse_ipv6_empty_bad);
612316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/hostname-good",
613316e8ee8SJuraj Marcin test_inet_parse_hostname_good);
614316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/all-options-good",
615316e8ee8SJuraj Marcin test_inet_parse_all_options_good);
616316e8ee8SJuraj Marcin g_test_add_func("/util/socket/inet-parse/all-bare-bool-good",
617316e8ee8SJuraj Marcin test_inet_parse_all_implicit_bool_good);
618316e8ee8SJuraj Marcin
619a4eb74a6SMarc-André Lureau end:
62058dc31f1SDaniel P. Berrange return g_test_run();
62158dc31f1SDaniel P. Berrange }
622