1c95031a1SLaurent Vivier /* 2c95031a1SLaurent Vivier * QTest testcase for netdev stream and dgram 3c95031a1SLaurent Vivier * 4c95031a1SLaurent Vivier * Copyright (c) 2022 Red Hat, Inc. 5c95031a1SLaurent Vivier * 6c95031a1SLaurent Vivier * SPDX-License-Identifier: GPL-2.0-or-later 7c95031a1SLaurent Vivier */ 8c95031a1SLaurent Vivier 9c95031a1SLaurent Vivier #include "qemu/osdep.h" 10c95031a1SLaurent Vivier #include "qemu/sockets.h" 11c95031a1SLaurent Vivier #include <glib/gstdio.h> 12c95031a1SLaurent Vivier #include "../unit/socket-helpers.h" 13c95031a1SLaurent Vivier #include "libqtest.h" 14c95031a1SLaurent Vivier 15*417296c8SPeter Maydell #define CONNECTION_TIMEOUT 60 16c95031a1SLaurent Vivier 17c95031a1SLaurent Vivier #define EXPECT_STATE(q, e, t) \ 18c95031a1SLaurent Vivier do { \ 19c95031a1SLaurent Vivier char *resp = NULL; \ 20c95031a1SLaurent Vivier g_test_timer_start(); \ 21c95031a1SLaurent Vivier do { \ 22c95031a1SLaurent Vivier g_free(resp); \ 23c95031a1SLaurent Vivier resp = qtest_hmp(q, "info network"); \ 24c95031a1SLaurent Vivier if (t) { \ 25c95031a1SLaurent Vivier strrchr(resp, t)[0] = 0; \ 26c95031a1SLaurent Vivier } \ 27c95031a1SLaurent Vivier if (g_str_equal(resp, e)) { \ 28c95031a1SLaurent Vivier break; \ 29c95031a1SLaurent Vivier } \ 30c95031a1SLaurent Vivier } while (g_test_timer_elapsed() < CONNECTION_TIMEOUT); \ 31c95031a1SLaurent Vivier g_assert_cmpstr(resp, ==, e); \ 32c95031a1SLaurent Vivier g_free(resp); \ 33c95031a1SLaurent Vivier } while (0) 34c95031a1SLaurent Vivier 35c95031a1SLaurent Vivier static gchar *tmpdir; 36c95031a1SLaurent Vivier 37c95031a1SLaurent Vivier static int inet_get_free_port_socket_ipv4(int sock) 38c95031a1SLaurent Vivier { 39c95031a1SLaurent Vivier struct sockaddr_in addr; 40c95031a1SLaurent Vivier socklen_t len; 41c95031a1SLaurent Vivier 42c95031a1SLaurent Vivier memset(&addr, 0, sizeof(addr)); 43c95031a1SLaurent Vivier addr.sin_family = AF_INET; 44c95031a1SLaurent Vivier addr.sin_addr.s_addr = INADDR_ANY; 45c95031a1SLaurent Vivier addr.sin_port = 0; 46c95031a1SLaurent Vivier if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 47c95031a1SLaurent Vivier return -1; 48c95031a1SLaurent Vivier } 49c95031a1SLaurent Vivier 50c95031a1SLaurent Vivier len = sizeof(addr); 51c95031a1SLaurent Vivier if (getsockname(sock, (struct sockaddr *)&addr, &len) < 0) { 52c95031a1SLaurent Vivier return -1; 53c95031a1SLaurent Vivier } 54c95031a1SLaurent Vivier 55c95031a1SLaurent Vivier return ntohs(addr.sin_port); 56c95031a1SLaurent Vivier } 57c95031a1SLaurent Vivier 58c95031a1SLaurent Vivier static int inet_get_free_port_socket_ipv6(int sock) 59c95031a1SLaurent Vivier { 60c95031a1SLaurent Vivier struct sockaddr_in6 addr; 61c95031a1SLaurent Vivier socklen_t len; 62c95031a1SLaurent Vivier 63c95031a1SLaurent Vivier memset(&addr, 0, sizeof(addr)); 64c95031a1SLaurent Vivier addr.sin6_family = AF_INET6; 65c95031a1SLaurent Vivier addr.sin6_addr = in6addr_any; 66c95031a1SLaurent Vivier addr.sin6_port = 0; 67c95031a1SLaurent Vivier if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 68c95031a1SLaurent Vivier return -1; 69c95031a1SLaurent Vivier } 70c95031a1SLaurent Vivier 71c95031a1SLaurent Vivier len = sizeof(addr); 72c95031a1SLaurent Vivier if (getsockname(sock, (struct sockaddr *)&addr, &len) < 0) { 73c95031a1SLaurent Vivier return -1; 74c95031a1SLaurent Vivier } 75c95031a1SLaurent Vivier 76c95031a1SLaurent Vivier return ntohs(addr.sin6_port); 77c95031a1SLaurent Vivier } 78c95031a1SLaurent Vivier 79c95031a1SLaurent Vivier static int inet_get_free_port_multiple(int nb, int *port, bool ipv6) 80c95031a1SLaurent Vivier { 81c95031a1SLaurent Vivier int sock[nb]; 82c95031a1SLaurent Vivier int i; 83c95031a1SLaurent Vivier 84c95031a1SLaurent Vivier for (i = 0; i < nb; i++) { 85c95031a1SLaurent Vivier sock[i] = socket(ipv6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0); 86c95031a1SLaurent Vivier if (sock[i] < 0) { 87c95031a1SLaurent Vivier break; 88c95031a1SLaurent Vivier } 89c95031a1SLaurent Vivier port[i] = ipv6 ? inet_get_free_port_socket_ipv6(sock[i]) : 90c95031a1SLaurent Vivier inet_get_free_port_socket_ipv4(sock[i]); 91c95031a1SLaurent Vivier if (port[i] == -1) { 92c95031a1SLaurent Vivier break; 93c95031a1SLaurent Vivier } 94c95031a1SLaurent Vivier } 95c95031a1SLaurent Vivier 96c95031a1SLaurent Vivier nb = i; 97c95031a1SLaurent Vivier for (i = 0; i < nb; i++) { 98c95031a1SLaurent Vivier closesocket(sock[i]); 99c95031a1SLaurent Vivier } 100c95031a1SLaurent Vivier 101c95031a1SLaurent Vivier return nb; 102c95031a1SLaurent Vivier } 103c95031a1SLaurent Vivier 104c95031a1SLaurent Vivier static int inet_get_free_port(bool ipv6) 105c95031a1SLaurent Vivier { 106c95031a1SLaurent Vivier int nb, port; 107c95031a1SLaurent Vivier 108c95031a1SLaurent Vivier nb = inet_get_free_port_multiple(1, &port, ipv6); 109c95031a1SLaurent Vivier g_assert_cmpint(nb, ==, 1); 110c95031a1SLaurent Vivier 111c95031a1SLaurent Vivier return port; 112c95031a1SLaurent Vivier } 113c95031a1SLaurent Vivier 114c95031a1SLaurent Vivier static void test_stream_inet_ipv4(void) 115c95031a1SLaurent Vivier { 116c95031a1SLaurent Vivier QTestState *qts0, *qts1; 117c95031a1SLaurent Vivier char *expect; 118c95031a1SLaurent Vivier int port; 119c95031a1SLaurent Vivier 120c95031a1SLaurent Vivier port = inet_get_free_port(false); 121c95031a1SLaurent Vivier qts0 = qtest_initf("-nodefaults -M none " 122c95031a1SLaurent Vivier "-netdev stream,id=st0,server=true,addr.type=inet," 123c95031a1SLaurent Vivier "addr.ipv4=on,addr.ipv6=off," 124c95031a1SLaurent Vivier "addr.host=127.0.0.1,addr.port=%d", port); 125c95031a1SLaurent Vivier 126c95031a1SLaurent Vivier EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0); 127c95031a1SLaurent Vivier 128c95031a1SLaurent Vivier qts1 = qtest_initf("-nodefaults -M none " 129c95031a1SLaurent Vivier "-netdev stream,server=false,id=st0,addr.type=inet," 130c95031a1SLaurent Vivier "addr.ipv4=on,addr.ipv6=off," 131c95031a1SLaurent Vivier "addr.host=127.0.0.1,addr.port=%d", port); 132c95031a1SLaurent Vivier 133c95031a1SLaurent Vivier expect = g_strdup_printf("st0: index=0,type=stream,tcp:127.0.0.1:%d\r\n", 134c95031a1SLaurent Vivier port); 135c95031a1SLaurent Vivier EXPECT_STATE(qts1, expect, 0); 136c95031a1SLaurent Vivier g_free(expect); 137c95031a1SLaurent Vivier 138c95031a1SLaurent Vivier /* the port is unknown, check only the address */ 139c95031a1SLaurent Vivier EXPECT_STATE(qts0, "st0: index=0,type=stream,tcp:127.0.0.1", ':'); 140c95031a1SLaurent Vivier 141c95031a1SLaurent Vivier qtest_quit(qts1); 142c95031a1SLaurent Vivier qtest_quit(qts0); 143c95031a1SLaurent Vivier } 144c95031a1SLaurent Vivier 145c95031a1SLaurent Vivier static void test_stream_inet_ipv6(void) 146c95031a1SLaurent Vivier { 147c95031a1SLaurent Vivier QTestState *qts0, *qts1; 148c95031a1SLaurent Vivier char *expect; 149c95031a1SLaurent Vivier int port; 150c95031a1SLaurent Vivier 151c95031a1SLaurent Vivier port = inet_get_free_port(true); 152c95031a1SLaurent Vivier qts0 = qtest_initf("-nodefaults -M none " 153c95031a1SLaurent Vivier "-netdev stream,id=st0,server=true,addr.type=inet," 154c95031a1SLaurent Vivier "addr.ipv4=off,addr.ipv6=on," 155c95031a1SLaurent Vivier "addr.host=::1,addr.port=%d", port); 156c95031a1SLaurent Vivier 157c95031a1SLaurent Vivier EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0); 158c95031a1SLaurent Vivier 159c95031a1SLaurent Vivier qts1 = qtest_initf("-nodefaults -M none " 160c95031a1SLaurent Vivier "-netdev stream,server=false,id=st0,addr.type=inet," 161c95031a1SLaurent Vivier "addr.ipv4=off,addr.ipv6=on," 162c95031a1SLaurent Vivier "addr.host=::1,addr.port=%d", port); 163c95031a1SLaurent Vivier 164c95031a1SLaurent Vivier expect = g_strdup_printf("st0: index=0,type=stream,tcp:::1:%d\r\n", 165c95031a1SLaurent Vivier port); 166c95031a1SLaurent Vivier EXPECT_STATE(qts1, expect, 0); 167c95031a1SLaurent Vivier g_free(expect); 168c95031a1SLaurent Vivier 169c95031a1SLaurent Vivier /* the port is unknown, check only the address */ 170c95031a1SLaurent Vivier EXPECT_STATE(qts0, "st0: index=0,type=stream,tcp:::1", ':'); 171c95031a1SLaurent Vivier 172c95031a1SLaurent Vivier qtest_quit(qts1); 173c95031a1SLaurent Vivier qtest_quit(qts0); 174c95031a1SLaurent Vivier } 175c95031a1SLaurent Vivier 176c95031a1SLaurent Vivier static void test_stream_unix(void) 177c95031a1SLaurent Vivier { 178c95031a1SLaurent Vivier QTestState *qts0, *qts1; 179c95031a1SLaurent Vivier char *expect; 180c95031a1SLaurent Vivier gchar *path; 181c95031a1SLaurent Vivier 182c95031a1SLaurent Vivier path = g_strconcat(tmpdir, "/stream_unix", NULL); 183c95031a1SLaurent Vivier 184c95031a1SLaurent Vivier qts0 = qtest_initf("-nodefaults -M none " 185c95031a1SLaurent Vivier "-netdev stream,id=st0,server=true," 186c95031a1SLaurent Vivier "addr.type=unix,addr.path=%s,", 187c95031a1SLaurent Vivier path); 188c95031a1SLaurent Vivier 189c95031a1SLaurent Vivier EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0); 190c95031a1SLaurent Vivier 191c95031a1SLaurent Vivier qts1 = qtest_initf("-nodefaults -M none " 192c95031a1SLaurent Vivier "-netdev stream,id=st0,server=false," 193c95031a1SLaurent Vivier "addr.type=unix,addr.path=%s", 194c95031a1SLaurent Vivier path); 195c95031a1SLaurent Vivier 196c95031a1SLaurent Vivier expect = g_strdup_printf("st0: index=0,type=stream,unix:%s\r\n", path); 197c95031a1SLaurent Vivier EXPECT_STATE(qts1, expect, 0); 198c95031a1SLaurent Vivier EXPECT_STATE(qts0, expect, 0); 199c95031a1SLaurent Vivier g_free(expect); 200c95031a1SLaurent Vivier g_free(path); 201c95031a1SLaurent Vivier 202c95031a1SLaurent Vivier qtest_quit(qts1); 203c95031a1SLaurent Vivier qtest_quit(qts0); 204c95031a1SLaurent Vivier } 205c95031a1SLaurent Vivier 206c95031a1SLaurent Vivier #ifdef CONFIG_LINUX 207c95031a1SLaurent Vivier static void test_stream_unix_abstract(void) 208c95031a1SLaurent Vivier { 209c95031a1SLaurent Vivier QTestState *qts0, *qts1; 210c95031a1SLaurent Vivier char *expect; 211c95031a1SLaurent Vivier gchar *path; 212c95031a1SLaurent Vivier 213c95031a1SLaurent Vivier path = g_strconcat(tmpdir, "/stream_unix_abstract", NULL); 214c95031a1SLaurent Vivier 215c95031a1SLaurent Vivier qts0 = qtest_initf("-nodefaults -M none " 216c95031a1SLaurent Vivier "-netdev stream,id=st0,server=true," 217c95031a1SLaurent Vivier "addr.type=unix,addr.path=%s," 218c95031a1SLaurent Vivier "addr.abstract=on", 219c95031a1SLaurent Vivier path); 220c95031a1SLaurent Vivier 221c95031a1SLaurent Vivier EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0); 222c95031a1SLaurent Vivier 223c95031a1SLaurent Vivier qts1 = qtest_initf("-nodefaults -M none " 224c95031a1SLaurent Vivier "-netdev stream,id=st0,server=false," 225c95031a1SLaurent Vivier "addr.type=unix,addr.path=%s,addr.abstract=on", 226c95031a1SLaurent Vivier path); 227c95031a1SLaurent Vivier 228c95031a1SLaurent Vivier expect = g_strdup_printf("st0: index=0,type=stream,unix:%s\r\n", path); 229c95031a1SLaurent Vivier EXPECT_STATE(qts1, expect, 0); 230c95031a1SLaurent Vivier EXPECT_STATE(qts0, expect, 0); 231c95031a1SLaurent Vivier g_free(expect); 232c95031a1SLaurent Vivier g_free(path); 233c95031a1SLaurent Vivier 234c95031a1SLaurent Vivier qtest_quit(qts1); 235c95031a1SLaurent Vivier qtest_quit(qts0); 236c95031a1SLaurent Vivier } 237c95031a1SLaurent Vivier #endif 238c95031a1SLaurent Vivier 239c95031a1SLaurent Vivier #ifndef _WIN32 240c95031a1SLaurent Vivier static void test_stream_fd(void) 241c95031a1SLaurent Vivier { 242c95031a1SLaurent Vivier QTestState *qts0, *qts1; 243c95031a1SLaurent Vivier int sock[2]; 244c95031a1SLaurent Vivier int ret; 245c95031a1SLaurent Vivier 246c95031a1SLaurent Vivier ret = socketpair(AF_LOCAL, SOCK_STREAM, 0, sock); 247c95031a1SLaurent Vivier g_assert_true(ret == 0); 248c95031a1SLaurent Vivier 249c95031a1SLaurent Vivier qts0 = qtest_initf("-nodefaults -M none " 250c95031a1SLaurent Vivier "-netdev stream,id=st0,addr.type=fd,addr.str=%d", 251c95031a1SLaurent Vivier sock[0]); 252c95031a1SLaurent Vivier 253c95031a1SLaurent Vivier EXPECT_STATE(qts0, "st0: index=0,type=stream,unix:\r\n", 0); 254c95031a1SLaurent Vivier 255c95031a1SLaurent Vivier qts1 = qtest_initf("-nodefaults -M none " 256c95031a1SLaurent Vivier "-netdev stream,id=st0,addr.type=fd,addr.str=%d", 257c95031a1SLaurent Vivier sock[1]); 258c95031a1SLaurent Vivier 259c95031a1SLaurent Vivier EXPECT_STATE(qts1, "st0: index=0,type=stream,unix:\r\n", 0); 260c95031a1SLaurent Vivier EXPECT_STATE(qts0, "st0: index=0,type=stream,unix:\r\n", 0); 261c95031a1SLaurent Vivier 262c95031a1SLaurent Vivier qtest_quit(qts1); 263c95031a1SLaurent Vivier qtest_quit(qts0); 264c95031a1SLaurent Vivier 265c95031a1SLaurent Vivier closesocket(sock[0]); 266c95031a1SLaurent Vivier closesocket(sock[1]); 267c95031a1SLaurent Vivier } 268c95031a1SLaurent Vivier #endif 269c95031a1SLaurent Vivier 270c95031a1SLaurent Vivier static void test_dgram_inet(void) 271c95031a1SLaurent Vivier { 272c95031a1SLaurent Vivier QTestState *qts0, *qts1; 273c95031a1SLaurent Vivier char *expect; 274c95031a1SLaurent Vivier int port[2]; 275c95031a1SLaurent Vivier int nb; 276c95031a1SLaurent Vivier 277c95031a1SLaurent Vivier nb = inet_get_free_port_multiple(2, port, false); 278c95031a1SLaurent Vivier g_assert_cmpint(nb, ==, 2); 279c95031a1SLaurent Vivier 280c95031a1SLaurent Vivier qts0 = qtest_initf("-nodefaults -M none " 281c95031a1SLaurent Vivier "-netdev dgram,id=st0," 282c95031a1SLaurent Vivier "local.type=inet,local.host=127.0.0.1,local.port=%d," 283c95031a1SLaurent Vivier "remote.type=inet,remote.host=127.0.0.1,remote.port=%d", 284c95031a1SLaurent Vivier port[0], port[1]); 285c95031a1SLaurent Vivier 286c95031a1SLaurent Vivier expect = g_strdup_printf("st0: index=0,type=dgram," 287c95031a1SLaurent Vivier "udp=127.0.0.1:%d/127.0.0.1:%d\r\n", 288c95031a1SLaurent Vivier port[0], port[1]); 289c95031a1SLaurent Vivier EXPECT_STATE(qts0, expect, 0); 290c95031a1SLaurent Vivier g_free(expect); 291c95031a1SLaurent Vivier 292c95031a1SLaurent Vivier qts1 = qtest_initf("-nodefaults -M none " 293c95031a1SLaurent Vivier "-netdev dgram,id=st0," 294c95031a1SLaurent Vivier "local.type=inet,local.host=127.0.0.1,local.port=%d," 295c95031a1SLaurent Vivier "remote.type=inet,remote.host=127.0.0.1,remote.port=%d", 296c95031a1SLaurent Vivier port[1], port[0]); 297c95031a1SLaurent Vivier 298c95031a1SLaurent Vivier expect = g_strdup_printf("st0: index=0,type=dgram," 299c95031a1SLaurent Vivier "udp=127.0.0.1:%d/127.0.0.1:%d\r\n", 300c95031a1SLaurent Vivier port[1], port[0]); 301c95031a1SLaurent Vivier EXPECT_STATE(qts1, expect, 0); 302c95031a1SLaurent Vivier g_free(expect); 303c95031a1SLaurent Vivier 304c95031a1SLaurent Vivier qtest_quit(qts1); 305c95031a1SLaurent Vivier qtest_quit(qts0); 306c95031a1SLaurent Vivier } 307c95031a1SLaurent Vivier 308c95031a1SLaurent Vivier #ifndef _WIN32 309c95031a1SLaurent Vivier static void test_dgram_mcast(void) 310c95031a1SLaurent Vivier { 311c95031a1SLaurent Vivier QTestState *qts; 312c95031a1SLaurent Vivier 313c95031a1SLaurent Vivier qts = qtest_initf("-nodefaults -M none " 314c95031a1SLaurent Vivier "-netdev dgram,id=st0," 315c95031a1SLaurent Vivier "remote.type=inet,remote.host=230.0.0.1,remote.port=1234"); 316c95031a1SLaurent Vivier 317c95031a1SLaurent Vivier EXPECT_STATE(qts, "st0: index=0,type=dgram,mcast=230.0.0.1:1234\r\n", 0); 318c95031a1SLaurent Vivier 319c95031a1SLaurent Vivier qtest_quit(qts); 320c95031a1SLaurent Vivier } 321c95031a1SLaurent Vivier 322c95031a1SLaurent Vivier static void test_dgram_unix(void) 323c95031a1SLaurent Vivier { 324c95031a1SLaurent Vivier QTestState *qts0, *qts1; 325c95031a1SLaurent Vivier char *expect; 326c95031a1SLaurent Vivier gchar *path0, *path1; 327c95031a1SLaurent Vivier 328c95031a1SLaurent Vivier path0 = g_strconcat(tmpdir, "/dgram_unix0", NULL); 329c95031a1SLaurent Vivier path1 = g_strconcat(tmpdir, "/dgram_unix1", NULL); 330c95031a1SLaurent Vivier 331c95031a1SLaurent Vivier qts0 = qtest_initf("-nodefaults -M none " 332c95031a1SLaurent Vivier "-netdev dgram,id=st0,local.type=unix,local.path=%s," 333c95031a1SLaurent Vivier "remote.type=unix,remote.path=%s", 334c95031a1SLaurent Vivier path0, path1); 335c95031a1SLaurent Vivier 336c95031a1SLaurent Vivier expect = g_strdup_printf("st0: index=0,type=dgram,udp=%s:%s\r\n", 337c95031a1SLaurent Vivier path0, path1); 338c95031a1SLaurent Vivier EXPECT_STATE(qts0, expect, 0); 339c95031a1SLaurent Vivier g_free(expect); 340c95031a1SLaurent Vivier 341c95031a1SLaurent Vivier qts1 = qtest_initf("-nodefaults -M none " 342c95031a1SLaurent Vivier "-netdev dgram,id=st0,local.type=unix,local.path=%s," 343c95031a1SLaurent Vivier "remote.type=unix,remote.path=%s", 344c95031a1SLaurent Vivier path1, path0); 345c95031a1SLaurent Vivier 346c95031a1SLaurent Vivier 347c95031a1SLaurent Vivier expect = g_strdup_printf("st0: index=0,type=dgram,udp=%s:%s\r\n", 348c95031a1SLaurent Vivier path1, path0); 349c95031a1SLaurent Vivier EXPECT_STATE(qts1, expect, 0); 350c95031a1SLaurent Vivier g_free(expect); 351c95031a1SLaurent Vivier 352c95031a1SLaurent Vivier unlink(path0); 353c95031a1SLaurent Vivier g_free(path0); 354c95031a1SLaurent Vivier unlink(path1); 355c95031a1SLaurent Vivier g_free(path1); 356c95031a1SLaurent Vivier 357c95031a1SLaurent Vivier qtest_quit(qts1); 358c95031a1SLaurent Vivier qtest_quit(qts0); 359c95031a1SLaurent Vivier } 360c95031a1SLaurent Vivier 361c95031a1SLaurent Vivier static void test_dgram_fd(void) 362c95031a1SLaurent Vivier { 363c95031a1SLaurent Vivier QTestState *qts0, *qts1; 364c95031a1SLaurent Vivier char *expect; 365c95031a1SLaurent Vivier int ret; 366c95031a1SLaurent Vivier int sv[2]; 367c95031a1SLaurent Vivier 368c95031a1SLaurent Vivier ret = socketpair(PF_UNIX, SOCK_DGRAM, 0, sv); 369c95031a1SLaurent Vivier g_assert_cmpint(ret, !=, -1); 370c95031a1SLaurent Vivier 371c95031a1SLaurent Vivier qts0 = qtest_initf("-nodefaults -M none " 372c95031a1SLaurent Vivier "-netdev dgram,id=st0,local.type=fd,local.str=%d", 373c95031a1SLaurent Vivier sv[0]); 374c95031a1SLaurent Vivier 375c95031a1SLaurent Vivier expect = g_strdup_printf("st0: index=0,type=dgram,fd=%d unix\r\n", sv[0]); 376c95031a1SLaurent Vivier EXPECT_STATE(qts0, expect, 0); 377c95031a1SLaurent Vivier g_free(expect); 378c95031a1SLaurent Vivier 379c95031a1SLaurent Vivier qts1 = qtest_initf("-nodefaults -M none " 380c95031a1SLaurent Vivier "-netdev dgram,id=st0,local.type=fd,local.str=%d", 381c95031a1SLaurent Vivier sv[1]); 382c95031a1SLaurent Vivier 383c95031a1SLaurent Vivier 384c95031a1SLaurent Vivier expect = g_strdup_printf("st0: index=0,type=dgram,fd=%d unix\r\n", sv[1]); 385c95031a1SLaurent Vivier EXPECT_STATE(qts1, expect, 0); 386c95031a1SLaurent Vivier g_free(expect); 387c95031a1SLaurent Vivier 388c95031a1SLaurent Vivier qtest_quit(qts1); 389c95031a1SLaurent Vivier qtest_quit(qts0); 390c95031a1SLaurent Vivier 391c95031a1SLaurent Vivier closesocket(sv[0]); 392c95031a1SLaurent Vivier closesocket(sv[1]); 393c95031a1SLaurent Vivier } 394c95031a1SLaurent Vivier #endif 395c95031a1SLaurent Vivier 396c95031a1SLaurent Vivier int main(int argc, char **argv) 397c95031a1SLaurent Vivier { 398c95031a1SLaurent Vivier int ret; 399c95031a1SLaurent Vivier bool has_ipv4, has_ipv6, has_afunix; 400c95031a1SLaurent Vivier g_autoptr(GError) err = NULL; 401c95031a1SLaurent Vivier 402c95031a1SLaurent Vivier socket_init(); 403c95031a1SLaurent Vivier g_test_init(&argc, &argv, NULL); 404c95031a1SLaurent Vivier 405c95031a1SLaurent Vivier if (socket_check_protocol_support(&has_ipv4, &has_ipv6) < 0) { 406c95031a1SLaurent Vivier g_error("socket_check_protocol_support() failed\n"); 407c95031a1SLaurent Vivier } 408c95031a1SLaurent Vivier 409c95031a1SLaurent Vivier tmpdir = g_dir_make_tmp("netdev-socket.XXXXXX", &err); 410c95031a1SLaurent Vivier if (tmpdir == NULL) { 411c95031a1SLaurent Vivier g_error("Can't create temporary directory in %s: %s", 412c95031a1SLaurent Vivier g_get_tmp_dir(), err->message); 413c95031a1SLaurent Vivier } 414c95031a1SLaurent Vivier 415c95031a1SLaurent Vivier if (has_ipv4) { 416c95031a1SLaurent Vivier qtest_add_func("/netdev/stream/inet/ipv4", test_stream_inet_ipv4); 417c95031a1SLaurent Vivier qtest_add_func("/netdev/dgram/inet", test_dgram_inet); 418c95031a1SLaurent Vivier #ifndef _WIN32 419c95031a1SLaurent Vivier qtest_add_func("/netdev/dgram/mcast", test_dgram_mcast); 420c95031a1SLaurent Vivier #endif 421c95031a1SLaurent Vivier } 422c95031a1SLaurent Vivier if (has_ipv6) { 423c95031a1SLaurent Vivier qtest_add_func("/netdev/stream/inet/ipv6", test_stream_inet_ipv6); 424c95031a1SLaurent Vivier } 425c95031a1SLaurent Vivier 426c95031a1SLaurent Vivier socket_check_afunix_support(&has_afunix); 427c95031a1SLaurent Vivier if (has_afunix) { 428c95031a1SLaurent Vivier #ifndef _WIN32 429c95031a1SLaurent Vivier qtest_add_func("/netdev/dgram/unix", test_dgram_unix); 430c95031a1SLaurent Vivier #endif 431c95031a1SLaurent Vivier qtest_add_func("/netdev/stream/unix", test_stream_unix); 432c95031a1SLaurent Vivier #ifdef CONFIG_LINUX 433c95031a1SLaurent Vivier qtest_add_func("/netdev/stream/unix/abstract", 434c95031a1SLaurent Vivier test_stream_unix_abstract); 435c95031a1SLaurent Vivier #endif 436c95031a1SLaurent Vivier #ifndef _WIN32 437c95031a1SLaurent Vivier qtest_add_func("/netdev/stream/fd", test_stream_fd); 438c95031a1SLaurent Vivier qtest_add_func("/netdev/dgram/fd", test_dgram_fd); 439c95031a1SLaurent Vivier #endif 440c95031a1SLaurent Vivier } 441c95031a1SLaurent Vivier 442c95031a1SLaurent Vivier ret = g_test_run(); 443c95031a1SLaurent Vivier 444c95031a1SLaurent Vivier g_rmdir(tmpdir); 445c95031a1SLaurent Vivier g_free(tmpdir); 446c95031a1SLaurent Vivier 447c95031a1SLaurent Vivier return ret; 448c95031a1SLaurent Vivier } 449