xref: /openbmc/qemu/tests/qtest/netdev-socket.c (revision c95031a19f0d7f418a597243f6f84b031a858997)
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