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