1 /*
2  * QEMU I/O channel sockets test
3  *
4  * Copyright (c) 2015-2016 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #include "qemu/osdep.h"
22 #include "io/channel-socket.h"
23 #include "io/channel-util.h"
24 #include "io-channel-helpers.h"
25 #include "socket-helpers.h"
26 #include "qapi/error.h"
27 #include "qemu/module.h"
28 
29 
test_io_channel_set_socket_bufs(QIOChannel * src,QIOChannel * dst)30 static void test_io_channel_set_socket_bufs(QIOChannel *src,
31                                             QIOChannel *dst)
32 {
33     int buflen = 64 * 1024;
34 
35     /*
36      * Make the socket buffers small so that we see
37      * the effects of partial reads/writes
38      */
39     setsockopt(((QIOChannelSocket *)src)->fd,
40                SOL_SOCKET, SO_SNDBUF,
41                (char *)&buflen,
42                sizeof(buflen));
43 
44     setsockopt(((QIOChannelSocket *)dst)->fd,
45                SOL_SOCKET, SO_SNDBUF,
46                (char *)&buflen,
47                sizeof(buflen));
48 }
49 
50 
test_io_channel_setup_sync(SocketAddress * listen_addr,SocketAddress * connect_addr,QIOChannel ** srv,QIOChannel ** src,QIOChannel ** dst)51 static void test_io_channel_setup_sync(SocketAddress *listen_addr,
52                                        SocketAddress *connect_addr,
53                                        QIOChannel **srv,
54                                        QIOChannel **src,
55                                        QIOChannel **dst)
56 {
57     QIOChannelSocket *lioc;
58 
59     lioc = qio_channel_socket_new();
60     qio_channel_socket_listen_sync(lioc, listen_addr, 1, &error_abort);
61 
62     if (listen_addr->type == SOCKET_ADDRESS_TYPE_INET) {
63         SocketAddress *laddr = qio_channel_socket_get_local_address(
64             lioc, &error_abort);
65 
66         g_free(connect_addr->u.inet.port);
67         connect_addr->u.inet.port = g_strdup(laddr->u.inet.port);
68 
69         qapi_free_SocketAddress(laddr);
70     }
71 
72     *src = QIO_CHANNEL(qio_channel_socket_new());
73     qio_channel_socket_connect_sync(
74         QIO_CHANNEL_SOCKET(*src), connect_addr, &error_abort);
75     qio_channel_set_delay(*src, false);
76 
77     qio_channel_wait(QIO_CHANNEL(lioc), G_IO_IN);
78     *dst = QIO_CHANNEL(qio_channel_socket_accept(lioc, &error_abort));
79     g_assert(*dst);
80 
81     test_io_channel_set_socket_bufs(*src, *dst);
82 
83     *srv = QIO_CHANNEL(lioc);
84 }
85 
86 
87 struct TestIOChannelData {
88     bool err;
89     GMainLoop *loop;
90 };
91 
92 
test_io_channel_complete(QIOTask * task,gpointer opaque)93 static void test_io_channel_complete(QIOTask *task,
94                                      gpointer opaque)
95 {
96     struct TestIOChannelData *data = opaque;
97     data->err = qio_task_propagate_error(task, NULL);
98     g_main_loop_quit(data->loop);
99 }
100 
101 
test_io_channel_setup_async(SocketAddress * listen_addr,SocketAddress * connect_addr,QIOChannel ** srv,QIOChannel ** src,QIOChannel ** dst)102 static void test_io_channel_setup_async(SocketAddress *listen_addr,
103                                         SocketAddress *connect_addr,
104                                         QIOChannel **srv,
105                                         QIOChannel **src,
106                                         QIOChannel **dst)
107 {
108     QIOChannelSocket *lioc;
109     struct TestIOChannelData data;
110 
111     data.loop = g_main_loop_new(g_main_context_default(),
112                                 TRUE);
113 
114     lioc = qio_channel_socket_new();
115     qio_channel_socket_listen_async(
116         lioc, listen_addr, 1,
117         test_io_channel_complete, &data, NULL, NULL);
118 
119     g_main_loop_run(data.loop);
120     g_main_context_iteration(g_main_context_default(), FALSE);
121 
122     g_assert(!data.err);
123 
124     if (listen_addr->type == SOCKET_ADDRESS_TYPE_INET) {
125         SocketAddress *laddr = qio_channel_socket_get_local_address(
126             lioc, &error_abort);
127 
128         g_free(connect_addr->u.inet.port);
129         connect_addr->u.inet.port = g_strdup(laddr->u.inet.port);
130 
131         qapi_free_SocketAddress(laddr);
132     }
133 
134     *src = QIO_CHANNEL(qio_channel_socket_new());
135 
136     qio_channel_socket_connect_async(
137         QIO_CHANNEL_SOCKET(*src), connect_addr,
138         test_io_channel_complete, &data, NULL, NULL);
139 
140     g_main_loop_run(data.loop);
141     g_main_context_iteration(g_main_context_default(), FALSE);
142 
143     g_assert(!data.err);
144 
145     qio_channel_wait(QIO_CHANNEL(lioc), G_IO_IN);
146     *dst = QIO_CHANNEL(qio_channel_socket_accept(lioc, &error_abort));
147     g_assert(*dst);
148 
149     qio_channel_set_delay(*src, false);
150     test_io_channel_set_socket_bufs(*src, *dst);
151 
152     *srv = QIO_CHANNEL(lioc);
153 
154     g_main_loop_unref(data.loop);
155 }
156 
157 
test_io_channel_socket_path_exists(SocketAddress * addr,bool expectExists)158 static void test_io_channel_socket_path_exists(SocketAddress *addr,
159                                                bool expectExists)
160 {
161     if (addr->type != SOCKET_ADDRESS_TYPE_UNIX) {
162         return;
163     }
164 
165     g_assert(g_file_test(addr->u.q_unix.path,
166                          G_FILE_TEST_EXISTS) == expectExists);
167 }
168 
169 
test_io_channel(bool async,SocketAddress * listen_addr,SocketAddress * connect_addr,bool passFD)170 static void test_io_channel(bool async,
171                             SocketAddress *listen_addr,
172                             SocketAddress *connect_addr,
173                             bool passFD)
174 {
175     QIOChannel *src, *dst, *srv;
176     QIOChannelTest *test;
177     if (async) {
178         test_io_channel_setup_async(listen_addr, connect_addr,
179                                     &srv, &src, &dst);
180 
181         g_assert(!passFD ||
182                  qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
183         g_assert(!passFD ||
184                  qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
185         g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN));
186         g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN));
187 
188         test_io_channel_socket_path_exists(listen_addr, true);
189 
190         test = qio_channel_test_new();
191         qio_channel_test_run_threads(test, true, src, dst);
192         qio_channel_test_validate(test);
193 
194         test_io_channel_socket_path_exists(listen_addr, true);
195 
196         /* unref without close, to ensure finalize() cleans up */
197 
198         object_unref(OBJECT(src));
199         object_unref(OBJECT(dst));
200         test_io_channel_socket_path_exists(listen_addr, true);
201 
202         object_unref(OBJECT(srv));
203         test_io_channel_socket_path_exists(listen_addr, false);
204 
205         test_io_channel_setup_async(listen_addr, connect_addr,
206                                     &srv, &src, &dst);
207 
208         g_assert(!passFD ||
209                  qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
210         g_assert(!passFD ||
211                  qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
212         g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN));
213         g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN));
214 
215         test = qio_channel_test_new();
216         qio_channel_test_run_threads(test, false, src, dst);
217         qio_channel_test_validate(test);
218 
219         /* close before unref, to ensure finalize copes with already closed */
220 
221         qio_channel_close(src, &error_abort);
222         qio_channel_close(dst, &error_abort);
223         test_io_channel_socket_path_exists(listen_addr, true);
224 
225         object_unref(OBJECT(src));
226         object_unref(OBJECT(dst));
227         test_io_channel_socket_path_exists(listen_addr, true);
228 
229         qio_channel_close(srv, &error_abort);
230         test_io_channel_socket_path_exists(listen_addr, false);
231 
232         object_unref(OBJECT(srv));
233         test_io_channel_socket_path_exists(listen_addr, false);
234     } else {
235         test_io_channel_setup_sync(listen_addr, connect_addr,
236                                    &srv, &src, &dst);
237 
238         g_assert(!passFD ||
239                  qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
240         g_assert(!passFD ||
241                  qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
242         g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN));
243         g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN));
244 
245         test_io_channel_socket_path_exists(listen_addr, true);
246 
247         test = qio_channel_test_new();
248         qio_channel_test_run_threads(test, true, src, dst);
249         qio_channel_test_validate(test);
250 
251         test_io_channel_socket_path_exists(listen_addr, true);
252 
253         /* unref without close, to ensure finalize() cleans up */
254 
255         object_unref(OBJECT(src));
256         object_unref(OBJECT(dst));
257         test_io_channel_socket_path_exists(listen_addr, true);
258 
259         object_unref(OBJECT(srv));
260         test_io_channel_socket_path_exists(listen_addr, false);
261 
262         test_io_channel_setup_sync(listen_addr, connect_addr,
263                                    &srv, &src, &dst);
264 
265         g_assert(!passFD ||
266                  qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
267         g_assert(!passFD ||
268                  qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
269         g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN));
270         g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN));
271 
272         test = qio_channel_test_new();
273         qio_channel_test_run_threads(test, false, src, dst);
274         qio_channel_test_validate(test);
275 
276         test_io_channel_socket_path_exists(listen_addr, true);
277 
278         /* close before unref, to ensure finalize copes with already closed */
279 
280         qio_channel_close(src, &error_abort);
281         qio_channel_close(dst, &error_abort);
282         test_io_channel_socket_path_exists(listen_addr, true);
283 
284         object_unref(OBJECT(src));
285         object_unref(OBJECT(dst));
286         test_io_channel_socket_path_exists(listen_addr, true);
287 
288         qio_channel_close(srv, &error_abort);
289         test_io_channel_socket_path_exists(listen_addr, false);
290 
291         object_unref(OBJECT(srv));
292         test_io_channel_socket_path_exists(listen_addr, false);
293     }
294 }
295 
296 
test_io_channel_ipv4(bool async)297 static void test_io_channel_ipv4(bool async)
298 {
299     SocketAddress *listen_addr = g_new0(SocketAddress, 1);
300     SocketAddress *connect_addr = g_new0(SocketAddress, 1);
301 
302     listen_addr->type = SOCKET_ADDRESS_TYPE_INET;
303     listen_addr->u.inet = (InetSocketAddress) {
304         .host = g_strdup("127.0.0.1"),
305         .port = NULL, /* Auto-select */
306     };
307 
308     connect_addr->type = SOCKET_ADDRESS_TYPE_INET;
309     connect_addr->u.inet = (InetSocketAddress) {
310         .host = g_strdup("127.0.0.1"),
311         .port = NULL, /* Filled in later */
312     };
313 
314     test_io_channel(async, listen_addr, connect_addr, false);
315 
316     qapi_free_SocketAddress(listen_addr);
317     qapi_free_SocketAddress(connect_addr);
318 }
319 
320 
test_io_channel_ipv4_sync(void)321 static void test_io_channel_ipv4_sync(void)
322 {
323     return test_io_channel_ipv4(false);
324 }
325 
326 
test_io_channel_ipv4_async(void)327 static void test_io_channel_ipv4_async(void)
328 {
329     return test_io_channel_ipv4(true);
330 }
331 
332 
test_io_channel_ipv6(bool async)333 static void test_io_channel_ipv6(bool async)
334 {
335     SocketAddress *listen_addr = g_new0(SocketAddress, 1);
336     SocketAddress *connect_addr = g_new0(SocketAddress, 1);
337 
338     listen_addr->type = SOCKET_ADDRESS_TYPE_INET;
339     listen_addr->u.inet = (InetSocketAddress) {
340         .host = g_strdup("::1"),
341         .port = NULL, /* Auto-select */
342     };
343 
344     connect_addr->type = SOCKET_ADDRESS_TYPE_INET;
345     connect_addr->u.inet = (InetSocketAddress) {
346         .host = g_strdup("::1"),
347         .port = NULL, /* Filled in later */
348     };
349 
350     test_io_channel(async, listen_addr, connect_addr, false);
351 
352     qapi_free_SocketAddress(listen_addr);
353     qapi_free_SocketAddress(connect_addr);
354 }
355 
356 
test_io_channel_ipv6_sync(void)357 static void test_io_channel_ipv6_sync(void)
358 {
359     return test_io_channel_ipv6(false);
360 }
361 
362 
test_io_channel_ipv6_async(void)363 static void test_io_channel_ipv6_async(void)
364 {
365     return test_io_channel_ipv6(true);
366 }
367 
368 
369 #ifndef _WIN32
test_io_channel_unix(bool async)370 static void test_io_channel_unix(bool async)
371 {
372     SocketAddress *listen_addr = g_new0(SocketAddress, 1);
373     SocketAddress *connect_addr = g_new0(SocketAddress, 1);
374 
375 #define TEST_SOCKET "test-io-channel-socket.sock"
376     listen_addr->type = SOCKET_ADDRESS_TYPE_UNIX;
377     listen_addr->u.q_unix.path = g_strdup(TEST_SOCKET);
378 
379     connect_addr->type = SOCKET_ADDRESS_TYPE_UNIX;
380     connect_addr->u.q_unix.path = g_strdup(TEST_SOCKET);
381 
382     test_io_channel(async, listen_addr, connect_addr, true);
383 
384     qapi_free_SocketAddress(listen_addr);
385     qapi_free_SocketAddress(connect_addr);
386 }
387 
388 
test_io_channel_unix_sync(void)389 static void test_io_channel_unix_sync(void)
390 {
391     return test_io_channel_unix(false);
392 }
393 
394 
test_io_channel_unix_async(void)395 static void test_io_channel_unix_async(void)
396 {
397     return test_io_channel_unix(true);
398 }
399 
test_io_channel_unix_fd_pass(void)400 static void test_io_channel_unix_fd_pass(void)
401 {
402     SocketAddress *listen_addr = g_new0(SocketAddress, 1);
403     SocketAddress *connect_addr = g_new0(SocketAddress, 1);
404     QIOChannel *src, *dst, *srv;
405     int testfd;
406     int fdsend[3];
407     int *fdrecv = NULL;
408     size_t nfdrecv = 0;
409     size_t i;
410     char bufsend[12], bufrecv[12];
411     struct iovec iosend[1], iorecv[1];
412 
413 #define TEST_SOCKET "test-io-channel-socket.sock"
414 #define TEST_FILE "test-io-channel-socket.txt"
415 
416     testfd = open(TEST_FILE, O_RDWR|O_TRUNC|O_CREAT, 0700);
417     g_assert(testfd != -1);
418     fdsend[0] = testfd;
419     fdsend[1] = testfd;
420     fdsend[2] = testfd;
421 
422     listen_addr->type = SOCKET_ADDRESS_TYPE_UNIX;
423     listen_addr->u.q_unix.path = g_strdup(TEST_SOCKET);
424 
425     connect_addr->type = SOCKET_ADDRESS_TYPE_UNIX;
426     connect_addr->u.q_unix.path = g_strdup(TEST_SOCKET);
427 
428     test_io_channel_setup_sync(listen_addr, connect_addr, &srv, &src, &dst);
429 
430     memcpy(bufsend, "Hello World", G_N_ELEMENTS(bufsend));
431 
432     iosend[0].iov_base = bufsend;
433     iosend[0].iov_len = G_N_ELEMENTS(bufsend);
434 
435     iorecv[0].iov_base = bufrecv;
436     iorecv[0].iov_len = G_N_ELEMENTS(bufrecv);
437 
438     g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
439     g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
440 
441     qio_channel_writev_full(src,
442                             iosend,
443                             G_N_ELEMENTS(iosend),
444                             fdsend,
445                             G_N_ELEMENTS(fdsend),
446                             &error_abort);
447 
448     qio_channel_readv_full(dst,
449                            iorecv,
450                            G_N_ELEMENTS(iorecv),
451                            &fdrecv,
452                            &nfdrecv,
453                            &error_abort);
454 
455     g_assert(nfdrecv == G_N_ELEMENTS(fdsend));
456     /* Each recvd FD should be different from sent FD */
457     for (i = 0; i < nfdrecv; i++) {
458         g_assert_cmpint(fdrecv[i], !=, testfd);
459     }
460     /* Each recvd FD should be different from each other */
461     g_assert_cmpint(fdrecv[0], !=, fdrecv[1]);
462     g_assert_cmpint(fdrecv[0], !=, fdrecv[2]);
463     g_assert_cmpint(fdrecv[1], !=, fdrecv[2]);
464 
465     /* Check the I/O buf we sent at the same time matches */
466     g_assert(memcmp(bufsend, bufrecv, G_N_ELEMENTS(bufsend)) == 0);
467 
468     /* Write some data into the FD we received */
469     g_assert(write(fdrecv[0], bufsend, G_N_ELEMENTS(bufsend)) ==
470              G_N_ELEMENTS(bufsend));
471 
472     /* Read data from the original FD and make sure it matches */
473     memset(bufrecv, 0, G_N_ELEMENTS(bufrecv));
474     g_assert(lseek(testfd, 0, SEEK_SET) == 0);
475     g_assert(read(testfd, bufrecv, G_N_ELEMENTS(bufrecv)) ==
476              G_N_ELEMENTS(bufrecv));
477     g_assert(memcmp(bufsend, bufrecv, G_N_ELEMENTS(bufsend)) == 0);
478 
479     object_unref(OBJECT(src));
480     object_unref(OBJECT(dst));
481     object_unref(OBJECT(srv));
482     qapi_free_SocketAddress(listen_addr);
483     qapi_free_SocketAddress(connect_addr);
484     unlink(TEST_SOCKET);
485     unlink(TEST_FILE);
486     close(testfd);
487     for (i = 0; i < nfdrecv; i++) {
488         close(fdrecv[i]);
489     }
490     g_free(fdrecv);
491 }
492 
test_io_channel_unix_listen_cleanup(void)493 static void test_io_channel_unix_listen_cleanup(void)
494 {
495     QIOChannelSocket *ioc;
496     struct sockaddr_un un;
497     int sock;
498 
499 #define TEST_SOCKET "test-io-channel-socket.sock"
500 
501     ioc = qio_channel_socket_new();
502 
503     /* Manually bind ioc without calling the qio api to avoid setting
504      * the LISTEN feature */
505     sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
506     memset(&un, 0, sizeof(un));
507     un.sun_family = AF_UNIX;
508     snprintf(un.sun_path, sizeof(un.sun_path), "%s", TEST_SOCKET);
509     unlink(TEST_SOCKET);
510     bind(sock, (struct sockaddr *)&un, sizeof(un));
511     ioc->fd = sock;
512     ioc->localAddrLen = sizeof(ioc->localAddr);
513     getsockname(sock, (struct sockaddr *)&ioc->localAddr,
514                 &ioc->localAddrLen);
515 
516     g_assert(g_file_test(TEST_SOCKET, G_FILE_TEST_EXISTS));
517     object_unref(OBJECT(ioc));
518     g_assert(g_file_test(TEST_SOCKET, G_FILE_TEST_EXISTS));
519 
520     unlink(TEST_SOCKET);
521 }
522 
523 #endif /* _WIN32 */
524 
525 
test_io_channel_ipv4_fd(void)526 static void test_io_channel_ipv4_fd(void)
527 {
528     QIOChannel *ioc;
529     int fd = -1;
530     struct sockaddr_in sa = {
531         .sin_family = AF_INET,
532         .sin_addr = {
533             .s_addr =  htonl(INADDR_LOOPBACK),
534         }
535         /* Leave port unset for auto-assign */
536     };
537     socklen_t salen = sizeof(sa);
538 
539     fd = socket(AF_INET, SOCK_STREAM, 0);
540     g_assert_cmpint(fd, >, -1);
541 
542     g_assert_cmpint(bind(fd, (struct sockaddr *)&sa, salen), ==, 0);
543 
544     ioc = qio_channel_new_fd(fd, &error_abort);
545 
546     g_assert_cmpstr(object_get_typename(OBJECT(ioc)),
547                     ==,
548                     TYPE_QIO_CHANNEL_SOCKET);
549 
550     object_unref(OBJECT(ioc));
551 }
552 
553 
main(int argc,char ** argv)554 int main(int argc, char **argv)
555 {
556     bool has_ipv4, has_ipv6;
557 
558     module_call_init(MODULE_INIT_QOM);
559     socket_init();
560 
561     g_test_init(&argc, &argv, NULL);
562 
563     /* We're creating actual IPv4/6 sockets, so we should
564      * check if the host running tests actually supports
565      * each protocol to avoid breaking tests on machines
566      * with either IPv4 or IPv6 disabled.
567      */
568     if (socket_check_protocol_support(&has_ipv4, &has_ipv6) < 0) {
569         g_printerr("socket_check_protocol_support() failed\n");
570         goto end;
571     }
572 
573     if (has_ipv4) {
574         g_test_add_func("/io/channel/socket/ipv4-sync",
575                         test_io_channel_ipv4_sync);
576         g_test_add_func("/io/channel/socket/ipv4-async",
577                         test_io_channel_ipv4_async);
578         g_test_add_func("/io/channel/socket/ipv4-fd",
579                         test_io_channel_ipv4_fd);
580     }
581     if (has_ipv6) {
582         g_test_add_func("/io/channel/socket/ipv6-sync",
583                         test_io_channel_ipv6_sync);
584         g_test_add_func("/io/channel/socket/ipv6-async",
585                         test_io_channel_ipv6_async);
586     }
587 
588 #ifndef _WIN32
589     g_test_add_func("/io/channel/socket/unix-sync",
590                     test_io_channel_unix_sync);
591     g_test_add_func("/io/channel/socket/unix-async",
592                     test_io_channel_unix_async);
593     g_test_add_func("/io/channel/socket/unix-fd-pass",
594                     test_io_channel_unix_fd_pass);
595     g_test_add_func("/io/channel/socket/unix-listen-cleanup",
596                     test_io_channel_unix_listen_cleanup);
597 #endif /* _WIN32 */
598 
599 end:
600     return g_test_run();
601 }
602