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