]> git.proxmox.com Git - mirror_qemu.git/blob - chardev/char-socket.c
tests: add /char/console test
[mirror_qemu.git] / chardev / char-socket.c
1 /*
2 * QEMU System Emulator
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 #include "qemu/osdep.h"
25 #include "sysemu/char.h"
26 #include "io/channel-socket.h"
27 #include "io/channel-tls.h"
28 #include "qemu/error-report.h"
29 #include "qapi/error.h"
30 #include "qapi/clone-visitor.h"
31
32 #include "char-io.h"
33
34 /***********************************************************/
35 /* TCP Net console */
36
37 #define TCP_MAX_FDS 16
38
39 typedef struct {
40 Chardev parent;
41 QIOChannel *ioc; /* Client I/O channel */
42 QIOChannelSocket *sioc; /* Client master channel */
43 QIOChannelSocket *listen_ioc;
44 guint listen_tag;
45 QCryptoTLSCreds *tls_creds;
46 int connected;
47 int max_size;
48 int do_telnetopt;
49 int do_nodelay;
50 int *read_msgfds;
51 size_t read_msgfds_num;
52 int *write_msgfds;
53 size_t write_msgfds_num;
54
55 SocketAddress *addr;
56 bool is_listen;
57 bool is_telnet;
58
59 guint reconnect_timer;
60 int64_t reconnect_time;
61 bool connect_err_reported;
62 } SocketChardev;
63
64 #define SOCKET_CHARDEV(obj) \
65 OBJECT_CHECK(SocketChardev, (obj), TYPE_CHARDEV_SOCKET)
66
67 static gboolean socket_reconnect_timeout(gpointer opaque);
68
69 static void qemu_chr_socket_restart_timer(Chardev *chr)
70 {
71 SocketChardev *s = SOCKET_CHARDEV(chr);
72 char *name;
73
74 assert(s->connected == 0);
75 s->reconnect_timer = g_timeout_add_seconds(s->reconnect_time,
76 socket_reconnect_timeout, chr);
77 name = g_strdup_printf("chardev-socket-reconnect-%s", chr->label);
78 g_source_set_name_by_id(s->reconnect_timer, name);
79 g_free(name);
80 }
81
82 static void check_report_connect_error(Chardev *chr,
83 Error *err)
84 {
85 SocketChardev *s = SOCKET_CHARDEV(chr);
86
87 if (!s->connect_err_reported) {
88 error_report("Unable to connect character device %s: %s",
89 chr->label, error_get_pretty(err));
90 s->connect_err_reported = true;
91 }
92 qemu_chr_socket_restart_timer(chr);
93 }
94
95 static gboolean tcp_chr_accept(QIOChannel *chan,
96 GIOCondition cond,
97 void *opaque);
98
99 static int tcp_chr_read_poll(void *opaque);
100 static void tcp_chr_disconnect(Chardev *chr);
101
102 /* Called with chr_write_lock held. */
103 static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len)
104 {
105 SocketChardev *s = SOCKET_CHARDEV(chr);
106
107 if (s->connected) {
108 int ret = io_channel_send_full(s->ioc, buf, len,
109 s->write_msgfds,
110 s->write_msgfds_num);
111
112 /* free the written msgfds, no matter what */
113 if (s->write_msgfds_num) {
114 g_free(s->write_msgfds);
115 s->write_msgfds = 0;
116 s->write_msgfds_num = 0;
117 }
118
119 if (ret < 0 && errno != EAGAIN) {
120 if (tcp_chr_read_poll(chr) <= 0) {
121 tcp_chr_disconnect(chr);
122 return len;
123 } /* else let the read handler finish it properly */
124 }
125
126 return ret;
127 } else {
128 /* XXX: indicate an error ? */
129 return len;
130 }
131 }
132
133 static int tcp_chr_read_poll(void *opaque)
134 {
135 Chardev *chr = CHARDEV(opaque);
136 SocketChardev *s = SOCKET_CHARDEV(opaque);
137 if (!s->connected) {
138 return 0;
139 }
140 s->max_size = qemu_chr_be_can_write(chr);
141 return s->max_size;
142 }
143
144 #define IAC 255
145 #define IAC_BREAK 243
146 static void tcp_chr_process_IAC_bytes(Chardev *chr,
147 SocketChardev *s,
148 uint8_t *buf, int *size)
149 {
150 /* Handle any telnet client's basic IAC options to satisfy char by
151 * char mode with no echo. All IAC options will be removed from
152 * the buf and the do_telnetopt variable will be used to track the
153 * state of the width of the IAC information.
154 *
155 * IAC commands come in sets of 3 bytes with the exception of the
156 * "IAC BREAK" command and the double IAC.
157 */
158
159 int i;
160 int j = 0;
161
162 for (i = 0; i < *size; i++) {
163 if (s->do_telnetopt > 1) {
164 if ((unsigned char)buf[i] == IAC && s->do_telnetopt == 2) {
165 /* Double IAC means send an IAC */
166 if (j != i) {
167 buf[j] = buf[i];
168 }
169 j++;
170 s->do_telnetopt = 1;
171 } else {
172 if ((unsigned char)buf[i] == IAC_BREAK
173 && s->do_telnetopt == 2) {
174 /* Handle IAC break commands by sending a serial break */
175 qemu_chr_be_event(chr, CHR_EVENT_BREAK);
176 s->do_telnetopt++;
177 }
178 s->do_telnetopt++;
179 }
180 if (s->do_telnetopt >= 4) {
181 s->do_telnetopt = 1;
182 }
183 } else {
184 if ((unsigned char)buf[i] == IAC) {
185 s->do_telnetopt = 2;
186 } else {
187 if (j != i) {
188 buf[j] = buf[i];
189 }
190 j++;
191 }
192 }
193 }
194 *size = j;
195 }
196
197 static int tcp_get_msgfds(Chardev *chr, int *fds, int num)
198 {
199 SocketChardev *s = SOCKET_CHARDEV(chr);
200
201 int to_copy = (s->read_msgfds_num < num) ? s->read_msgfds_num : num;
202
203 assert(num <= TCP_MAX_FDS);
204
205 if (to_copy) {
206 int i;
207
208 memcpy(fds, s->read_msgfds, to_copy * sizeof(int));
209
210 /* Close unused fds */
211 for (i = to_copy; i < s->read_msgfds_num; i++) {
212 close(s->read_msgfds[i]);
213 }
214
215 g_free(s->read_msgfds);
216 s->read_msgfds = 0;
217 s->read_msgfds_num = 0;
218 }
219
220 return to_copy;
221 }
222
223 static int tcp_set_msgfds(Chardev *chr, int *fds, int num)
224 {
225 SocketChardev *s = SOCKET_CHARDEV(chr);
226
227 /* clear old pending fd array */
228 g_free(s->write_msgfds);
229 s->write_msgfds = NULL;
230 s->write_msgfds_num = 0;
231
232 if (!s->connected ||
233 !qio_channel_has_feature(s->ioc,
234 QIO_CHANNEL_FEATURE_FD_PASS)) {
235 return -1;
236 }
237
238 if (num) {
239 s->write_msgfds = g_new(int, num);
240 memcpy(s->write_msgfds, fds, num * sizeof(int));
241 }
242
243 s->write_msgfds_num = num;
244
245 return 0;
246 }
247
248 static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len)
249 {
250 SocketChardev *s = SOCKET_CHARDEV(chr);
251 struct iovec iov = { .iov_base = buf, .iov_len = len };
252 int ret;
253 size_t i;
254 int *msgfds = NULL;
255 size_t msgfds_num = 0;
256
257 if (qio_channel_has_feature(s->ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
258 ret = qio_channel_readv_full(s->ioc, &iov, 1,
259 &msgfds, &msgfds_num,
260 NULL);
261 } else {
262 ret = qio_channel_readv_full(s->ioc, &iov, 1,
263 NULL, NULL,
264 NULL);
265 }
266
267 if (ret == QIO_CHANNEL_ERR_BLOCK) {
268 errno = EAGAIN;
269 ret = -1;
270 } else if (ret == -1) {
271 errno = EIO;
272 }
273
274 if (msgfds_num) {
275 /* close and clean read_msgfds */
276 for (i = 0; i < s->read_msgfds_num; i++) {
277 close(s->read_msgfds[i]);
278 }
279
280 if (s->read_msgfds_num) {
281 g_free(s->read_msgfds);
282 }
283
284 s->read_msgfds = msgfds;
285 s->read_msgfds_num = msgfds_num;
286 }
287
288 for (i = 0; i < s->read_msgfds_num; i++) {
289 int fd = s->read_msgfds[i];
290 if (fd < 0) {
291 continue;
292 }
293
294 /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
295 qemu_set_block(fd);
296
297 #ifndef MSG_CMSG_CLOEXEC
298 qemu_set_cloexec(fd);
299 #endif
300 }
301
302 return ret;
303 }
304
305 static GSource *tcp_chr_add_watch(Chardev *chr, GIOCondition cond)
306 {
307 SocketChardev *s = SOCKET_CHARDEV(chr);
308 return qio_channel_create_watch(s->ioc, cond);
309 }
310
311 static void tcp_chr_free_connection(Chardev *chr)
312 {
313 SocketChardev *s = SOCKET_CHARDEV(chr);
314 int i;
315
316 if (!s->connected) {
317 return;
318 }
319
320 if (s->read_msgfds_num) {
321 for (i = 0; i < s->read_msgfds_num; i++) {
322 close(s->read_msgfds[i]);
323 }
324 g_free(s->read_msgfds);
325 s->read_msgfds = NULL;
326 s->read_msgfds_num = 0;
327 }
328
329 tcp_set_msgfds(chr, NULL, 0);
330 remove_fd_in_watch(chr, NULL);
331 object_unref(OBJECT(s->sioc));
332 s->sioc = NULL;
333 object_unref(OBJECT(s->ioc));
334 s->ioc = NULL;
335 g_free(chr->filename);
336 chr->filename = NULL;
337 s->connected = 0;
338 }
339
340 static char *SocketAddress_to_str(const char *prefix, SocketAddress *addr,
341 bool is_listen, bool is_telnet)
342 {
343 switch (addr->type) {
344 case SOCKET_ADDRESS_KIND_INET:
345 return g_strdup_printf("%s%s:%s:%s%s", prefix,
346 is_telnet ? "telnet" : "tcp",
347 addr->u.inet.data->host,
348 addr->u.inet.data->port,
349 is_listen ? ",server" : "");
350 break;
351 case SOCKET_ADDRESS_KIND_UNIX:
352 return g_strdup_printf("%sunix:%s%s", prefix,
353 addr->u.q_unix.data->path,
354 is_listen ? ",server" : "");
355 break;
356 case SOCKET_ADDRESS_KIND_FD:
357 return g_strdup_printf("%sfd:%s%s", prefix, addr->u.fd.data->str,
358 is_listen ? ",server" : "");
359 break;
360 case SOCKET_ADDRESS_KIND_VSOCK:
361 return g_strdup_printf("%svsock:%s:%s", prefix,
362 addr->u.vsock.data->cid,
363 addr->u.vsock.data->port);
364 default:
365 abort();
366 }
367 }
368
369 static void update_disconnected_filename(SocketChardev *s)
370 {
371 Chardev *chr = CHARDEV(s);
372
373 g_free(chr->filename);
374 chr->filename = SocketAddress_to_str("disconnected:", s->addr,
375 s->is_listen, s->is_telnet);
376 }
377
378 static void tcp_chr_disconnect(Chardev *chr)
379 {
380 SocketChardev *s = SOCKET_CHARDEV(chr);
381
382 if (!s->connected) {
383 return;
384 }
385
386 tcp_chr_free_connection(chr);
387
388 if (s->listen_ioc) {
389 s->listen_tag = qio_channel_add_watch(
390 QIO_CHANNEL(s->listen_ioc), G_IO_IN, tcp_chr_accept, chr, NULL);
391 }
392 update_disconnected_filename(s);
393 qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
394 if (s->reconnect_time) {
395 qemu_chr_socket_restart_timer(chr);
396 }
397 }
398
399 static gboolean tcp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
400 {
401 Chardev *chr = CHARDEV(opaque);
402 SocketChardev *s = SOCKET_CHARDEV(opaque);
403 uint8_t buf[CHR_READ_BUF_LEN];
404 int len, size;
405
406 if (!s->connected || s->max_size <= 0) {
407 return TRUE;
408 }
409 len = sizeof(buf);
410 if (len > s->max_size) {
411 len = s->max_size;
412 }
413 size = tcp_chr_recv(chr, (void *)buf, len);
414 if (size == 0 || size == -1) {
415 /* connection closed */
416 tcp_chr_disconnect(chr);
417 } else if (size > 0) {
418 if (s->do_telnetopt) {
419 tcp_chr_process_IAC_bytes(chr, s, buf, &size);
420 }
421 if (size > 0) {
422 qemu_chr_be_write(chr, buf, size);
423 }
424 }
425
426 return TRUE;
427 }
428
429 static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len)
430 {
431 SocketChardev *s = SOCKET_CHARDEV(chr);
432 int size;
433
434 if (!s->connected) {
435 return 0;
436 }
437
438 size = tcp_chr_recv(chr, (void *) buf, len);
439 if (size == 0) {
440 /* connection closed */
441 tcp_chr_disconnect(chr);
442 }
443
444 return size;
445 }
446
447 static char *sockaddr_to_str(struct sockaddr_storage *ss, socklen_t ss_len,
448 struct sockaddr_storage *ps, socklen_t ps_len,
449 bool is_listen, bool is_telnet)
450 {
451 char shost[NI_MAXHOST], sserv[NI_MAXSERV];
452 char phost[NI_MAXHOST], pserv[NI_MAXSERV];
453 const char *left = "", *right = "";
454
455 switch (ss->ss_family) {
456 #ifndef _WIN32
457 case AF_UNIX:
458 return g_strdup_printf("unix:%s%s",
459 ((struct sockaddr_un *)(ss))->sun_path,
460 is_listen ? ",server" : "");
461 #endif
462 case AF_INET6:
463 left = "[";
464 right = "]";
465 /* fall through */
466 case AF_INET:
467 getnameinfo((struct sockaddr *) ss, ss_len, shost, sizeof(shost),
468 sserv, sizeof(sserv), NI_NUMERICHOST | NI_NUMERICSERV);
469 getnameinfo((struct sockaddr *) ps, ps_len, phost, sizeof(phost),
470 pserv, sizeof(pserv), NI_NUMERICHOST | NI_NUMERICSERV);
471 return g_strdup_printf("%s:%s%s%s:%s%s <-> %s%s%s:%s",
472 is_telnet ? "telnet" : "tcp",
473 left, shost, right, sserv,
474 is_listen ? ",server" : "",
475 left, phost, right, pserv);
476
477 default:
478 return g_strdup_printf("unknown");
479 }
480 }
481
482 static void tcp_chr_connect(void *opaque)
483 {
484 Chardev *chr = CHARDEV(opaque);
485 SocketChardev *s = SOCKET_CHARDEV(opaque);
486
487 g_free(chr->filename);
488 chr->filename = sockaddr_to_str(
489 &s->sioc->localAddr, s->sioc->localAddrLen,
490 &s->sioc->remoteAddr, s->sioc->remoteAddrLen,
491 s->is_listen, s->is_telnet);
492
493 s->connected = 1;
494 if (s->ioc) {
495 chr->fd_in_tag = io_add_watch_poll(chr, s->ioc,
496 tcp_chr_read_poll,
497 tcp_chr_read,
498 chr, NULL);
499 }
500 qemu_chr_be_event(chr, CHR_EVENT_OPENED);
501 }
502
503 static void tcp_chr_update_read_handler(Chardev *chr,
504 GMainContext *context)
505 {
506 SocketChardev *s = SOCKET_CHARDEV(chr);
507
508 if (!s->connected) {
509 return;
510 }
511
512 remove_fd_in_watch(chr, NULL);
513 if (s->ioc) {
514 chr->fd_in_tag = io_add_watch_poll(chr, s->ioc,
515 tcp_chr_read_poll,
516 tcp_chr_read, chr,
517 context);
518 }
519 }
520
521 typedef struct {
522 Chardev *chr;
523 char buf[12];
524 size_t buflen;
525 } TCPChardevTelnetInit;
526
527 static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc,
528 GIOCondition cond G_GNUC_UNUSED,
529 gpointer user_data)
530 {
531 TCPChardevTelnetInit *init = user_data;
532 ssize_t ret;
533
534 ret = qio_channel_write(ioc, init->buf, init->buflen, NULL);
535 if (ret < 0) {
536 if (ret == QIO_CHANNEL_ERR_BLOCK) {
537 ret = 0;
538 } else {
539 tcp_chr_disconnect(init->chr);
540 return FALSE;
541 }
542 }
543 init->buflen -= ret;
544
545 if (init->buflen == 0) {
546 tcp_chr_connect(init->chr);
547 return FALSE;
548 }
549
550 memmove(init->buf, init->buf + ret, init->buflen);
551
552 return TRUE;
553 }
554
555 static void tcp_chr_telnet_init(Chardev *chr)
556 {
557 SocketChardev *s = SOCKET_CHARDEV(chr);
558 TCPChardevTelnetInit *init = g_new0(TCPChardevTelnetInit, 1);
559 size_t n = 0;
560
561 init->chr = chr;
562 init->buflen = 12;
563
564 #define IACSET(x, a, b, c) \
565 do { \
566 x[n++] = a; \
567 x[n++] = b; \
568 x[n++] = c; \
569 } while (0)
570
571 /* Prep the telnet negotion to put telnet in binary,
572 * no echo, single char mode */
573 IACSET(init->buf, 0xff, 0xfb, 0x01); /* IAC WILL ECHO */
574 IACSET(init->buf, 0xff, 0xfb, 0x03); /* IAC WILL Suppress go ahead */
575 IACSET(init->buf, 0xff, 0xfb, 0x00); /* IAC WILL Binary */
576 IACSET(init->buf, 0xff, 0xfd, 0x00); /* IAC DO Binary */
577
578 #undef IACSET
579
580 qio_channel_add_watch(
581 s->ioc, G_IO_OUT,
582 tcp_chr_telnet_init_io,
583 init, NULL);
584 }
585
586
587 static void tcp_chr_tls_handshake(QIOTask *task,
588 gpointer user_data)
589 {
590 Chardev *chr = user_data;
591 SocketChardev *s = user_data;
592
593 if (qio_task_propagate_error(task, NULL)) {
594 tcp_chr_disconnect(chr);
595 } else {
596 if (s->do_telnetopt) {
597 tcp_chr_telnet_init(chr);
598 } else {
599 tcp_chr_connect(chr);
600 }
601 }
602 }
603
604
605 static void tcp_chr_tls_init(Chardev *chr)
606 {
607 SocketChardev *s = SOCKET_CHARDEV(chr);
608 QIOChannelTLS *tioc;
609 Error *err = NULL;
610 gchar *name;
611
612 if (s->is_listen) {
613 tioc = qio_channel_tls_new_server(
614 s->ioc, s->tls_creds,
615 NULL, /* XXX Use an ACL */
616 &err);
617 } else {
618 tioc = qio_channel_tls_new_client(
619 s->ioc, s->tls_creds,
620 s->addr->u.inet.data->host,
621 &err);
622 }
623 if (tioc == NULL) {
624 error_free(err);
625 tcp_chr_disconnect(chr);
626 return;
627 }
628 name = g_strdup_printf("chardev-tls-%s-%s",
629 s->is_listen ? "server" : "client",
630 chr->label);
631 qio_channel_set_name(QIO_CHANNEL(tioc), name);
632 g_free(name);
633 object_unref(OBJECT(s->ioc));
634 s->ioc = QIO_CHANNEL(tioc);
635
636 qio_channel_tls_handshake(tioc,
637 tcp_chr_tls_handshake,
638 chr,
639 NULL);
640 }
641
642
643 static void tcp_chr_set_client_ioc_name(Chardev *chr,
644 QIOChannelSocket *sioc)
645 {
646 SocketChardev *s = SOCKET_CHARDEV(chr);
647 char *name;
648 name = g_strdup_printf("chardev-tcp-%s-%s",
649 s->is_listen ? "server" : "client",
650 chr->label);
651 qio_channel_set_name(QIO_CHANNEL(sioc), name);
652 g_free(name);
653
654 }
655
656 static int tcp_chr_new_client(Chardev *chr, QIOChannelSocket *sioc)
657 {
658 SocketChardev *s = SOCKET_CHARDEV(chr);
659
660 if (s->ioc != NULL) {
661 return -1;
662 }
663
664 s->ioc = QIO_CHANNEL(sioc);
665 object_ref(OBJECT(sioc));
666 s->sioc = sioc;
667 object_ref(OBJECT(sioc));
668
669 qio_channel_set_blocking(s->ioc, false, NULL);
670
671 if (s->do_nodelay) {
672 qio_channel_set_delay(s->ioc, false);
673 }
674 if (s->listen_tag) {
675 g_source_remove(s->listen_tag);
676 s->listen_tag = 0;
677 }
678
679 if (s->tls_creds) {
680 tcp_chr_tls_init(chr);
681 } else {
682 if (s->do_telnetopt) {
683 tcp_chr_telnet_init(chr);
684 } else {
685 tcp_chr_connect(chr);
686 }
687 }
688
689 return 0;
690 }
691
692
693 static int tcp_chr_add_client(Chardev *chr, int fd)
694 {
695 int ret;
696 QIOChannelSocket *sioc;
697
698 sioc = qio_channel_socket_new_fd(fd, NULL);
699 if (!sioc) {
700 return -1;
701 }
702 tcp_chr_set_client_ioc_name(chr, sioc);
703 ret = tcp_chr_new_client(chr, sioc);
704 object_unref(OBJECT(sioc));
705 return ret;
706 }
707
708 static gboolean tcp_chr_accept(QIOChannel *channel,
709 GIOCondition cond,
710 void *opaque)
711 {
712 Chardev *chr = CHARDEV(opaque);
713 QIOChannelSocket *sioc;
714
715 sioc = qio_channel_socket_accept(QIO_CHANNEL_SOCKET(channel),
716 NULL);
717 if (!sioc) {
718 return TRUE;
719 }
720
721 tcp_chr_new_client(chr, sioc);
722
723 object_unref(OBJECT(sioc));
724
725 return TRUE;
726 }
727
728 static int tcp_chr_wait_connected(Chardev *chr, Error **errp)
729 {
730 SocketChardev *s = SOCKET_CHARDEV(chr);
731 QIOChannelSocket *sioc;
732
733 /* It can't wait on s->connected, since it is set asynchronously
734 * in TLS and telnet cases, only wait for an accepted socket */
735 while (!s->ioc) {
736 if (s->is_listen) {
737 error_report("QEMU waiting for connection on: %s",
738 chr->filename);
739 qio_channel_set_blocking(QIO_CHANNEL(s->listen_ioc), true, NULL);
740 tcp_chr_accept(QIO_CHANNEL(s->listen_ioc), G_IO_IN, chr);
741 qio_channel_set_blocking(QIO_CHANNEL(s->listen_ioc), false, NULL);
742 } else {
743 sioc = qio_channel_socket_new();
744 tcp_chr_set_client_ioc_name(chr, sioc);
745 if (qio_channel_socket_connect_sync(sioc, s->addr, errp) < 0) {
746 object_unref(OBJECT(sioc));
747 return -1;
748 }
749 tcp_chr_new_client(chr, sioc);
750 object_unref(OBJECT(sioc));
751 }
752 }
753
754 return 0;
755 }
756
757 static void char_socket_finalize(Object *obj)
758 {
759 Chardev *chr = CHARDEV(obj);
760 SocketChardev *s = SOCKET_CHARDEV(obj);
761
762 tcp_chr_free_connection(chr);
763
764 if (s->reconnect_timer) {
765 g_source_remove(s->reconnect_timer);
766 s->reconnect_timer = 0;
767 }
768 qapi_free_SocketAddress(s->addr);
769 if (s->listen_tag) {
770 g_source_remove(s->listen_tag);
771 s->listen_tag = 0;
772 }
773 if (s->listen_ioc) {
774 object_unref(OBJECT(s->listen_ioc));
775 }
776 if (s->tls_creds) {
777 object_unref(OBJECT(s->tls_creds));
778 }
779
780 qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
781 }
782
783 static void qemu_chr_socket_connected(QIOTask *task, void *opaque)
784 {
785 QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
786 Chardev *chr = CHARDEV(opaque);
787 SocketChardev *s = SOCKET_CHARDEV(chr);
788 Error *err = NULL;
789
790 if (qio_task_propagate_error(task, &err)) {
791 check_report_connect_error(chr, err);
792 error_free(err);
793 goto cleanup;
794 }
795
796 s->connect_err_reported = false;
797 tcp_chr_new_client(chr, sioc);
798
799 cleanup:
800 object_unref(OBJECT(sioc));
801 }
802
803 static gboolean socket_reconnect_timeout(gpointer opaque)
804 {
805 Chardev *chr = CHARDEV(opaque);
806 SocketChardev *s = SOCKET_CHARDEV(opaque);
807 QIOChannelSocket *sioc;
808
809 s->reconnect_timer = 0;
810
811 if (chr->be_open) {
812 return false;
813 }
814
815 sioc = qio_channel_socket_new();
816 tcp_chr_set_client_ioc_name(chr, sioc);
817 qio_channel_socket_connect_async(sioc, s->addr,
818 qemu_chr_socket_connected,
819 chr, NULL);
820
821 return false;
822 }
823
824 static void qmp_chardev_open_socket(Chardev *chr,
825 ChardevBackend *backend,
826 bool *be_opened,
827 Error **errp)
828 {
829 SocketChardev *s = SOCKET_CHARDEV(chr);
830 ChardevSocket *sock = backend->u.socket.data;
831 SocketAddress *addr = sock->addr;
832 bool do_nodelay = sock->has_nodelay ? sock->nodelay : false;
833 bool is_listen = sock->has_server ? sock->server : true;
834 bool is_telnet = sock->has_telnet ? sock->telnet : false;
835 bool is_waitconnect = sock->has_wait ? sock->wait : false;
836 int64_t reconnect = sock->has_reconnect ? sock->reconnect : 0;
837 QIOChannelSocket *sioc = NULL;
838
839 s->is_listen = is_listen;
840 s->is_telnet = is_telnet;
841 s->do_nodelay = do_nodelay;
842 if (sock->tls_creds) {
843 Object *creds;
844 creds = object_resolve_path_component(
845 object_get_objects_root(), sock->tls_creds);
846 if (!creds) {
847 error_setg(errp, "No TLS credentials with id '%s'",
848 sock->tls_creds);
849 goto error;
850 }
851 s->tls_creds = (QCryptoTLSCreds *)
852 object_dynamic_cast(creds,
853 TYPE_QCRYPTO_TLS_CREDS);
854 if (!s->tls_creds) {
855 error_setg(errp, "Object with id '%s' is not TLS credentials",
856 sock->tls_creds);
857 goto error;
858 }
859 object_ref(OBJECT(s->tls_creds));
860 if (is_listen) {
861 if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
862 error_setg(errp, "%s",
863 "Expected TLS credentials for server endpoint");
864 goto error;
865 }
866 } else {
867 if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
868 error_setg(errp, "%s",
869 "Expected TLS credentials for client endpoint");
870 goto error;
871 }
872 }
873 }
874
875 s->addr = QAPI_CLONE(SocketAddress, sock->addr);
876
877 qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE);
878 /* TODO SOCKET_ADDRESS_FD where fd has AF_UNIX */
879 if (addr->type == SOCKET_ADDRESS_KIND_UNIX) {
880 qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_FD_PASS);
881 }
882
883 /* be isn't opened until we get a connection */
884 *be_opened = false;
885
886 update_disconnected_filename(s);
887
888 if (is_listen) {
889 if (is_telnet) {
890 s->do_telnetopt = 1;
891 }
892 } else if (reconnect > 0) {
893 s->reconnect_time = reconnect;
894 }
895
896 if (s->reconnect_time) {
897 sioc = qio_channel_socket_new();
898 tcp_chr_set_client_ioc_name(chr, sioc);
899 qio_channel_socket_connect_async(sioc, s->addr,
900 qemu_chr_socket_connected,
901 chr, NULL);
902 } else {
903 if (s->is_listen) {
904 char *name;
905 sioc = qio_channel_socket_new();
906
907 name = g_strdup_printf("chardev-tcp-listener-%s", chr->label);
908 qio_channel_set_name(QIO_CHANNEL(sioc), name);
909 g_free(name);
910
911 if (qio_channel_socket_listen_sync(sioc, s->addr, errp) < 0) {
912 goto error;
913 }
914
915 qapi_free_SocketAddress(s->addr);
916 s->addr = socket_local_address(sioc->fd, errp);
917 update_disconnected_filename(s);
918
919 s->listen_ioc = sioc;
920 if (is_waitconnect &&
921 qemu_chr_wait_connected(chr, errp) < 0) {
922 return;
923 }
924 if (!s->ioc) {
925 s->listen_tag = qio_channel_add_watch(
926 QIO_CHANNEL(s->listen_ioc), G_IO_IN,
927 tcp_chr_accept, chr, NULL);
928 }
929 } else if (qemu_chr_wait_connected(chr, errp) < 0) {
930 goto error;
931 }
932 }
933
934 return;
935
936 error:
937 if (sioc) {
938 object_unref(OBJECT(sioc));
939 }
940 }
941
942 static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
943 Error **errp)
944 {
945 bool is_listen = qemu_opt_get_bool(opts, "server", false);
946 bool is_waitconnect = is_listen && qemu_opt_get_bool(opts, "wait", true);
947 bool is_telnet = qemu_opt_get_bool(opts, "telnet", false);
948 bool do_nodelay = !qemu_opt_get_bool(opts, "delay", true);
949 int64_t reconnect = qemu_opt_get_number(opts, "reconnect", 0);
950 const char *path = qemu_opt_get(opts, "path");
951 const char *host = qemu_opt_get(opts, "host");
952 const char *port = qemu_opt_get(opts, "port");
953 const char *tls_creds = qemu_opt_get(opts, "tls-creds");
954 SocketAddress *addr;
955 ChardevSocket *sock;
956
957 backend->type = CHARDEV_BACKEND_KIND_SOCKET;
958 if (!path) {
959 if (!host) {
960 error_setg(errp, "chardev: socket: no host given");
961 return;
962 }
963 if (!port) {
964 error_setg(errp, "chardev: socket: no port given");
965 return;
966 }
967 } else {
968 if (tls_creds) {
969 error_setg(errp, "TLS can only be used over TCP socket");
970 return;
971 }
972 }
973
974 sock = backend->u.socket.data = g_new0(ChardevSocket, 1);
975 qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock));
976
977 sock->has_nodelay = true;
978 sock->nodelay = do_nodelay;
979 sock->has_server = true;
980 sock->server = is_listen;
981 sock->has_telnet = true;
982 sock->telnet = is_telnet;
983 sock->has_wait = true;
984 sock->wait = is_waitconnect;
985 sock->has_reconnect = true;
986 sock->reconnect = reconnect;
987 sock->tls_creds = g_strdup(tls_creds);
988
989 addr = g_new0(SocketAddress, 1);
990 if (path) {
991 UnixSocketAddress *q_unix;
992 addr->type = SOCKET_ADDRESS_KIND_UNIX;
993 q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
994 q_unix->path = g_strdup(path);
995 } else {
996 addr->type = SOCKET_ADDRESS_KIND_INET;
997 addr->u.inet.data = g_new(InetSocketAddress, 1);
998 *addr->u.inet.data = (InetSocketAddress) {
999 .host = g_strdup(host),
1000 .port = g_strdup(port),
1001 .has_to = qemu_opt_get(opts, "to"),
1002 .to = qemu_opt_get_number(opts, "to", 0),
1003 .has_ipv4 = qemu_opt_get(opts, "ipv4"),
1004 .ipv4 = qemu_opt_get_bool(opts, "ipv4", 0),
1005 .has_ipv6 = qemu_opt_get(opts, "ipv6"),
1006 .ipv6 = qemu_opt_get_bool(opts, "ipv6", 0),
1007 };
1008 }
1009 sock->addr = addr;
1010 }
1011
1012 static void
1013 char_socket_get_addr(Object *obj, Visitor *v, const char *name,
1014 void *opaque, Error **errp)
1015 {
1016 SocketChardev *s = SOCKET_CHARDEV(obj);
1017
1018 visit_type_SocketAddress(v, name, &s->addr, errp);
1019 }
1020
1021 static bool
1022 char_socket_get_connected(Object *obj, Error **errp)
1023 {
1024 SocketChardev *s = SOCKET_CHARDEV(obj);
1025
1026 return s->connected;
1027 }
1028
1029 static void char_socket_class_init(ObjectClass *oc, void *data)
1030 {
1031 ChardevClass *cc = CHARDEV_CLASS(oc);
1032
1033 cc->parse = qemu_chr_parse_socket;
1034 cc->open = qmp_chardev_open_socket;
1035 cc->chr_wait_connected = tcp_chr_wait_connected;
1036 cc->chr_write = tcp_chr_write;
1037 cc->chr_sync_read = tcp_chr_sync_read;
1038 cc->chr_disconnect = tcp_chr_disconnect;
1039 cc->get_msgfds = tcp_get_msgfds;
1040 cc->set_msgfds = tcp_set_msgfds;
1041 cc->chr_add_client = tcp_chr_add_client;
1042 cc->chr_add_watch = tcp_chr_add_watch;
1043 cc->chr_update_read_handler = tcp_chr_update_read_handler;
1044
1045 object_class_property_add(oc, "addr", "SocketAddress",
1046 char_socket_get_addr, NULL,
1047 NULL, NULL, &error_abort);
1048
1049 object_class_property_add_bool(oc, "connected", char_socket_get_connected,
1050 NULL, &error_abort);
1051 }
1052
1053 static const TypeInfo char_socket_type_info = {
1054 .name = TYPE_CHARDEV_SOCKET,
1055 .parent = TYPE_CHARDEV,
1056 .instance_size = sizeof(SocketChardev),
1057 .instance_finalize = char_socket_finalize,
1058 .class_init = char_socket_class_init,
1059 };
1060
1061 static void register_types(void)
1062 {
1063 type_register_static(&char_socket_type_info);
1064 }
1065
1066 type_init(register_types);