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