xref: /openbmc/qemu/chardev/char-socket.c (revision ae3c12a0)
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 
25 #include "qemu/osdep.h"
26 #include "chardev/char.h"
27 #include "io/channel-socket.h"
28 #include "io/channel-tls.h"
29 #include "io/channel-websock.h"
30 #include "io/net-listener.h"
31 #include "qemu/error-report.h"
32 #include "qemu/option.h"
33 #include "qapi/error.h"
34 #include "qapi/clone-visitor.h"
35 #include "qapi/qapi-visit-sockets.h"
36 
37 #include "chardev/char-io.h"
38 
39 /***********************************************************/
40 /* TCP Net console */
41 
42 #define TCP_MAX_FDS 16
43 
44 typedef struct {
45     char buf[21];
46     size_t buflen;
47 } TCPChardevTelnetInit;
48 
49 typedef enum {
50     TCP_CHARDEV_STATE_DISCONNECTED,
51     TCP_CHARDEV_STATE_CONNECTING,
52     TCP_CHARDEV_STATE_CONNECTED,
53 } TCPChardevState;
54 
55 typedef struct {
56     Chardev parent;
57     QIOChannel *ioc; /* Client I/O channel */
58     QIOChannelSocket *sioc; /* Client master channel */
59     QIONetListener *listener;
60     GSource *hup_source;
61     QCryptoTLSCreds *tls_creds;
62     char *tls_authz;
63     TCPChardevState state;
64     int max_size;
65     int do_telnetopt;
66     int do_nodelay;
67     int *read_msgfds;
68     size_t read_msgfds_num;
69     int *write_msgfds;
70     size_t write_msgfds_num;
71 
72     SocketAddress *addr;
73     bool is_listen;
74     bool is_telnet;
75     bool is_tn3270;
76     GSource *telnet_source;
77     TCPChardevTelnetInit *telnet_init;
78 
79     bool is_websock;
80 
81     GSource *reconnect_timer;
82     int64_t reconnect_time;
83     bool connect_err_reported;
84 
85     QIOTask *connect_task;
86 } SocketChardev;
87 
88 #define SOCKET_CHARDEV(obj)                                     \
89     OBJECT_CHECK(SocketChardev, (obj), TYPE_CHARDEV_SOCKET)
90 
91 static gboolean socket_reconnect_timeout(gpointer opaque);
92 static void tcp_chr_telnet_init(Chardev *chr);
93 
94 static void tcp_chr_change_state(SocketChardev *s, TCPChardevState state)
95 {
96     switch (state) {
97     case TCP_CHARDEV_STATE_DISCONNECTED:
98         break;
99     case TCP_CHARDEV_STATE_CONNECTING:
100         assert(s->state == TCP_CHARDEV_STATE_DISCONNECTED);
101         break;
102     case TCP_CHARDEV_STATE_CONNECTED:
103         assert(s->state == TCP_CHARDEV_STATE_CONNECTING);
104         break;
105     }
106     s->state = state;
107 }
108 
109 static void tcp_chr_reconn_timer_cancel(SocketChardev *s)
110 {
111     if (s->reconnect_timer) {
112         g_source_destroy(s->reconnect_timer);
113         g_source_unref(s->reconnect_timer);
114         s->reconnect_timer = NULL;
115     }
116 }
117 
118 static void qemu_chr_socket_restart_timer(Chardev *chr)
119 {
120     SocketChardev *s = SOCKET_CHARDEV(chr);
121     char *name;
122 
123     assert(s->state == TCP_CHARDEV_STATE_DISCONNECTED);
124     assert(!s->reconnect_timer);
125     name = g_strdup_printf("chardev-socket-reconnect-%s", chr->label);
126     s->reconnect_timer = qemu_chr_timeout_add_ms(chr,
127                                                  s->reconnect_time * 1000,
128                                                  socket_reconnect_timeout,
129                                                  chr);
130     g_source_set_name(s->reconnect_timer, name);
131     g_free(name);
132 }
133 
134 static void check_report_connect_error(Chardev *chr,
135                                        Error *err)
136 {
137     SocketChardev *s = SOCKET_CHARDEV(chr);
138 
139     if (!s->connect_err_reported) {
140         error_report("Unable to connect character device %s: %s",
141                      chr->label, error_get_pretty(err));
142         s->connect_err_reported = true;
143     }
144     qemu_chr_socket_restart_timer(chr);
145 }
146 
147 static void tcp_chr_accept(QIONetListener *listener,
148                            QIOChannelSocket *cioc,
149                            void *opaque);
150 
151 static int tcp_chr_read_poll(void *opaque);
152 static void tcp_chr_disconnect(Chardev *chr);
153 
154 /* Called with chr_write_lock held.  */
155 static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len)
156 {
157     SocketChardev *s = SOCKET_CHARDEV(chr);
158 
159     if (s->state == TCP_CHARDEV_STATE_CONNECTED) {
160         int ret =  io_channel_send_full(s->ioc, buf, len,
161                                         s->write_msgfds,
162                                         s->write_msgfds_num);
163 
164         /* free the written msgfds in any cases
165          * other than ret < 0 && errno == EAGAIN
166          */
167         if (!(ret < 0 && EAGAIN == errno)
168             && s->write_msgfds_num) {
169             g_free(s->write_msgfds);
170             s->write_msgfds = 0;
171             s->write_msgfds_num = 0;
172         }
173 
174         if (ret < 0 && errno != EAGAIN) {
175             if (tcp_chr_read_poll(chr) <= 0) {
176                 tcp_chr_disconnect(chr);
177                 return len;
178             } /* else let the read handler finish it properly */
179         }
180 
181         return ret;
182     } else {
183         /* XXX: indicate an error ? */
184         return len;
185     }
186 }
187 
188 static int tcp_chr_read_poll(void *opaque)
189 {
190     Chardev *chr = CHARDEV(opaque);
191     SocketChardev *s = SOCKET_CHARDEV(opaque);
192     if (s->state != TCP_CHARDEV_STATE_CONNECTED) {
193         return 0;
194     }
195     s->max_size = qemu_chr_be_can_write(chr);
196     return s->max_size;
197 }
198 
199 static void tcp_chr_process_IAC_bytes(Chardev *chr,
200                                       SocketChardev *s,
201                                       uint8_t *buf, int *size)
202 {
203     /* Handle any telnet or tn3270 client's basic IAC options.
204      * For telnet options, it satisfies char by char mode with no echo.
205      * For tn3270 options, it satisfies binary mode with EOR.
206      * All IAC options will be removed from the buf and the do_opt
207      * pointer will be used to track the state of the width of the
208      * IAC information.
209      *
210      * RFC854: "All TELNET commands consist of at least a two byte sequence.
211      * The commands dealing with option negotiation are three byte sequences,
212      * the third byte being the code for the option referenced."
213      * "IAC BREAK", "IAC IP", "IAC NOP" and the double IAC are two bytes.
214      * "IAC SB", "IAC SE" and "IAC EOR" are saved to split up data boundary
215      * for tn3270.
216      * NOP, Break and Interrupt Process(IP) might be encountered during a TN3270
217      * session, and NOP and IP need to be done later.
218      */
219 
220     int i;
221     int j = 0;
222 
223     for (i = 0; i < *size; i++) {
224         if (s->do_telnetopt > 1) {
225             if ((unsigned char)buf[i] == IAC && s->do_telnetopt == 2) {
226                 /* Double IAC means send an IAC */
227                 if (j != i) {
228                     buf[j] = buf[i];
229                 }
230                 j++;
231                 s->do_telnetopt = 1;
232             } else {
233                 if ((unsigned char)buf[i] == IAC_BREAK
234                     && s->do_telnetopt == 2) {
235                     /* Handle IAC break commands by sending a serial break */
236                     qemu_chr_be_event(chr, CHR_EVENT_BREAK);
237                     s->do_telnetopt++;
238                 } else if (s->is_tn3270 && ((unsigned char)buf[i] == IAC_EOR
239                            || (unsigned char)buf[i] == IAC_SB
240                            || (unsigned char)buf[i] == IAC_SE)
241                            && s->do_telnetopt == 2) {
242                     buf[j++] = IAC;
243                     buf[j++] = buf[i];
244                     s->do_telnetopt++;
245                 } else if (s->is_tn3270 && ((unsigned char)buf[i] == IAC_IP
246                            || (unsigned char)buf[i] == IAC_NOP)
247                            && s->do_telnetopt == 2) {
248                     /* TODO: IP and NOP need to be implemented later. */
249                     s->do_telnetopt++;
250                 }
251                 s->do_telnetopt++;
252             }
253             if (s->do_telnetopt >= 4) {
254                 s->do_telnetopt = 1;
255             }
256         } else {
257             if ((unsigned char)buf[i] == IAC) {
258                 s->do_telnetopt = 2;
259             } else {
260                 if (j != i) {
261                     buf[j] = buf[i];
262                 }
263                 j++;
264             }
265         }
266     }
267     *size = j;
268 }
269 
270 static int tcp_get_msgfds(Chardev *chr, int *fds, int num)
271 {
272     SocketChardev *s = SOCKET_CHARDEV(chr);
273 
274     int to_copy = (s->read_msgfds_num < num) ? s->read_msgfds_num : num;
275 
276     assert(num <= TCP_MAX_FDS);
277 
278     if (to_copy) {
279         int i;
280 
281         memcpy(fds, s->read_msgfds, to_copy * sizeof(int));
282 
283         /* Close unused fds */
284         for (i = to_copy; i < s->read_msgfds_num; i++) {
285             close(s->read_msgfds[i]);
286         }
287 
288         g_free(s->read_msgfds);
289         s->read_msgfds = 0;
290         s->read_msgfds_num = 0;
291     }
292 
293     return to_copy;
294 }
295 
296 static int tcp_set_msgfds(Chardev *chr, int *fds, int num)
297 {
298     SocketChardev *s = SOCKET_CHARDEV(chr);
299 
300     /* clear old pending fd array */
301     g_free(s->write_msgfds);
302     s->write_msgfds = NULL;
303     s->write_msgfds_num = 0;
304 
305     if ((s->state != TCP_CHARDEV_STATE_CONNECTED) ||
306         !qio_channel_has_feature(s->ioc,
307                                  QIO_CHANNEL_FEATURE_FD_PASS)) {
308         return -1;
309     }
310 
311     if (num) {
312         s->write_msgfds = g_new(int, num);
313         memcpy(s->write_msgfds, fds, num * sizeof(int));
314     }
315 
316     s->write_msgfds_num = num;
317 
318     return 0;
319 }
320 
321 static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len)
322 {
323     SocketChardev *s = SOCKET_CHARDEV(chr);
324     struct iovec iov = { .iov_base = buf, .iov_len = len };
325     int ret;
326     size_t i;
327     int *msgfds = NULL;
328     size_t msgfds_num = 0;
329 
330     if (qio_channel_has_feature(s->ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
331         ret = qio_channel_readv_full(s->ioc, &iov, 1,
332                                      &msgfds, &msgfds_num,
333                                      NULL);
334     } else {
335         ret = qio_channel_readv_full(s->ioc, &iov, 1,
336                                      NULL, NULL,
337                                      NULL);
338     }
339 
340     if (ret == QIO_CHANNEL_ERR_BLOCK) {
341         errno = EAGAIN;
342         ret = -1;
343     } else if (ret == -1) {
344         errno = EIO;
345     }
346 
347     if (msgfds_num) {
348         /* close and clean read_msgfds */
349         for (i = 0; i < s->read_msgfds_num; i++) {
350             close(s->read_msgfds[i]);
351         }
352 
353         if (s->read_msgfds_num) {
354             g_free(s->read_msgfds);
355         }
356 
357         s->read_msgfds = msgfds;
358         s->read_msgfds_num = msgfds_num;
359     }
360 
361     for (i = 0; i < s->read_msgfds_num; i++) {
362         int fd = s->read_msgfds[i];
363         if (fd < 0) {
364             continue;
365         }
366 
367         /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
368         qemu_set_block(fd);
369 
370 #ifndef MSG_CMSG_CLOEXEC
371         qemu_set_cloexec(fd);
372 #endif
373     }
374 
375     return ret;
376 }
377 
378 static GSource *tcp_chr_add_watch(Chardev *chr, GIOCondition cond)
379 {
380     SocketChardev *s = SOCKET_CHARDEV(chr);
381     return qio_channel_create_watch(s->ioc, cond);
382 }
383 
384 static void remove_hup_source(SocketChardev *s)
385 {
386     if (s->hup_source != NULL) {
387         g_source_destroy(s->hup_source);
388         g_source_unref(s->hup_source);
389         s->hup_source = NULL;
390     }
391 }
392 
393 static void tcp_chr_free_connection(Chardev *chr)
394 {
395     SocketChardev *s = SOCKET_CHARDEV(chr);
396     int i;
397 
398     if (s->read_msgfds_num) {
399         for (i = 0; i < s->read_msgfds_num; i++) {
400             close(s->read_msgfds[i]);
401         }
402         g_free(s->read_msgfds);
403         s->read_msgfds = NULL;
404         s->read_msgfds_num = 0;
405     }
406 
407     remove_hup_source(s);
408 
409     tcp_set_msgfds(chr, NULL, 0);
410     remove_fd_in_watch(chr);
411     object_unref(OBJECT(s->sioc));
412     s->sioc = NULL;
413     object_unref(OBJECT(s->ioc));
414     s->ioc = NULL;
415     g_free(chr->filename);
416     chr->filename = NULL;
417     tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED);
418 }
419 
420 static const char *qemu_chr_socket_protocol(SocketChardev *s)
421 {
422     if (s->is_telnet) {
423         return "telnet";
424     }
425     return s->is_websock ? "websocket" : "tcp";
426 }
427 
428 static char *qemu_chr_socket_address(SocketChardev *s, const char *prefix)
429 {
430     switch (s->addr->type) {
431     case SOCKET_ADDRESS_TYPE_INET:
432         return g_strdup_printf("%s%s:%s:%s%s", prefix,
433                                qemu_chr_socket_protocol(s),
434                                s->addr->u.inet.host,
435                                s->addr->u.inet.port,
436                                s->is_listen ? ",server" : "");
437         break;
438     case SOCKET_ADDRESS_TYPE_UNIX:
439         return g_strdup_printf("%sunix:%s%s", prefix,
440                                s->addr->u.q_unix.path,
441                                s->is_listen ? ",server" : "");
442         break;
443     case SOCKET_ADDRESS_TYPE_FD:
444         return g_strdup_printf("%sfd:%s%s", prefix, s->addr->u.fd.str,
445                                s->is_listen ? ",server" : "");
446         break;
447     case SOCKET_ADDRESS_TYPE_VSOCK:
448         return g_strdup_printf("%svsock:%s:%s", prefix,
449                                s->addr->u.vsock.cid,
450                                s->addr->u.vsock.port);
451     default:
452         abort();
453     }
454 }
455 
456 static void update_disconnected_filename(SocketChardev *s)
457 {
458     Chardev *chr = CHARDEV(s);
459 
460     g_free(chr->filename);
461     if (s->addr) {
462         chr->filename = qemu_chr_socket_address(s, "disconnected:");
463     } else {
464         chr->filename = g_strdup("disconnected:socket");
465     }
466 }
467 
468 /* NB may be called even if tcp_chr_connect has not been
469  * reached, due to TLS or telnet initialization failure,
470  * so can *not* assume s->state == TCP_CHARDEV_STATE_CONNECTED
471  */
472 static void tcp_chr_disconnect(Chardev *chr)
473 {
474     SocketChardev *s = SOCKET_CHARDEV(chr);
475     bool emit_close = s->state == TCP_CHARDEV_STATE_CONNECTED;
476 
477     tcp_chr_free_connection(chr);
478 
479     if (s->listener) {
480         qio_net_listener_set_client_func_full(s->listener, tcp_chr_accept,
481                                               chr, NULL, chr->gcontext);
482     }
483     update_disconnected_filename(s);
484     if (emit_close) {
485         qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
486     }
487     if (s->reconnect_time) {
488         qemu_chr_socket_restart_timer(chr);
489     }
490 }
491 
492 static gboolean tcp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
493 {
494     Chardev *chr = CHARDEV(opaque);
495     SocketChardev *s = SOCKET_CHARDEV(opaque);
496     uint8_t buf[CHR_READ_BUF_LEN];
497     int len, size;
498 
499     if ((s->state != TCP_CHARDEV_STATE_CONNECTED) ||
500         s->max_size <= 0) {
501         return TRUE;
502     }
503     len = sizeof(buf);
504     if (len > s->max_size) {
505         len = s->max_size;
506     }
507     size = tcp_chr_recv(chr, (void *)buf, len);
508     if (size == 0 || (size == -1 && errno != EAGAIN)) {
509         /* connection closed */
510         tcp_chr_disconnect(chr);
511     } else if (size > 0) {
512         if (s->do_telnetopt) {
513             tcp_chr_process_IAC_bytes(chr, s, buf, &size);
514         }
515         if (size > 0) {
516             qemu_chr_be_write(chr, buf, size);
517         }
518     }
519 
520     return TRUE;
521 }
522 
523 static gboolean tcp_chr_hup(QIOChannel *channel,
524                                GIOCondition cond,
525                                void *opaque)
526 {
527     Chardev *chr = CHARDEV(opaque);
528     tcp_chr_disconnect(chr);
529     return G_SOURCE_REMOVE;
530 }
531 
532 static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len)
533 {
534     SocketChardev *s = SOCKET_CHARDEV(chr);
535     int size;
536 
537     if (s->state != TCP_CHARDEV_STATE_CONNECTED) {
538         return 0;
539     }
540 
541     qio_channel_set_blocking(s->ioc, true, NULL);
542     size = tcp_chr_recv(chr, (void *) buf, len);
543     qio_channel_set_blocking(s->ioc, false, NULL);
544     if (size == 0) {
545         /* connection closed */
546         tcp_chr_disconnect(chr);
547     }
548 
549     return size;
550 }
551 
552 static char *qemu_chr_compute_filename(SocketChardev *s)
553 {
554     struct sockaddr_storage *ss = &s->sioc->localAddr;
555     struct sockaddr_storage *ps = &s->sioc->remoteAddr;
556     socklen_t ss_len = s->sioc->localAddrLen;
557     socklen_t ps_len = s->sioc->remoteAddrLen;
558     char shost[NI_MAXHOST], sserv[NI_MAXSERV];
559     char phost[NI_MAXHOST], pserv[NI_MAXSERV];
560     const char *left = "", *right = "";
561 
562     switch (ss->ss_family) {
563 #ifndef _WIN32
564     case AF_UNIX:
565         return g_strdup_printf("unix:%s%s",
566                                ((struct sockaddr_un *)(ss))->sun_path,
567                                s->is_listen ? ",server" : "");
568 #endif
569     case AF_INET6:
570         left  = "[";
571         right = "]";
572         /* fall through */
573     case AF_INET:
574         getnameinfo((struct sockaddr *) ss, ss_len, shost, sizeof(shost),
575                     sserv, sizeof(sserv), NI_NUMERICHOST | NI_NUMERICSERV);
576         getnameinfo((struct sockaddr *) ps, ps_len, phost, sizeof(phost),
577                     pserv, sizeof(pserv), NI_NUMERICHOST | NI_NUMERICSERV);
578         return g_strdup_printf("%s:%s%s%s:%s%s <-> %s%s%s:%s",
579                                qemu_chr_socket_protocol(s),
580                                left, shost, right, sserv,
581                                s->is_listen ? ",server" : "",
582                                left, phost, right, pserv);
583 
584     default:
585         return g_strdup_printf("unknown");
586     }
587 }
588 
589 static void update_ioc_handlers(SocketChardev *s)
590 {
591     Chardev *chr = CHARDEV(s);
592 
593     if (s->state != TCP_CHARDEV_STATE_CONNECTED) {
594         return;
595     }
596 
597     remove_fd_in_watch(chr);
598     chr->gsource = io_add_watch_poll(chr, s->ioc,
599                                      tcp_chr_read_poll,
600                                      tcp_chr_read, chr,
601                                      chr->gcontext);
602 
603     remove_hup_source(s);
604     s->hup_source = qio_channel_create_watch(s->ioc, G_IO_HUP);
605     g_source_set_callback(s->hup_source, (GSourceFunc)tcp_chr_hup,
606                           chr, NULL);
607     g_source_attach(s->hup_source, chr->gcontext);
608 }
609 
610 static void tcp_chr_connect(void *opaque)
611 {
612     Chardev *chr = CHARDEV(opaque);
613     SocketChardev *s = SOCKET_CHARDEV(opaque);
614 
615     g_free(chr->filename);
616     chr->filename = qemu_chr_compute_filename(s);
617 
618     tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTED);
619     update_ioc_handlers(s);
620     qemu_chr_be_event(chr, CHR_EVENT_OPENED);
621 }
622 
623 static void tcp_chr_telnet_destroy(SocketChardev *s)
624 {
625     if (s->telnet_source) {
626         g_source_destroy(s->telnet_source);
627         g_source_unref(s->telnet_source);
628         s->telnet_source = NULL;
629     }
630 }
631 
632 static void tcp_chr_update_read_handler(Chardev *chr)
633 {
634     SocketChardev *s = SOCKET_CHARDEV(chr);
635 
636     if (s->listener && s->state == TCP_CHARDEV_STATE_DISCONNECTED) {
637         /*
638          * It's possible that chardev context is changed in
639          * qemu_chr_be_update_read_handlers().  Reset it for QIO net
640          * listener if there is.
641          */
642         qio_net_listener_set_client_func_full(s->listener, tcp_chr_accept,
643                                               chr, NULL, chr->gcontext);
644     }
645 
646     if (s->telnet_source) {
647         tcp_chr_telnet_init(CHARDEV(s));
648     }
649 
650     update_ioc_handlers(s);
651 }
652 
653 static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc,
654                                        GIOCondition cond G_GNUC_UNUSED,
655                                        gpointer user_data)
656 {
657     SocketChardev *s = user_data;
658     Chardev *chr = CHARDEV(s);
659     TCPChardevTelnetInit *init = s->telnet_init;
660     ssize_t ret;
661 
662     assert(init);
663 
664     ret = qio_channel_write(ioc, init->buf, init->buflen, NULL);
665     if (ret < 0) {
666         if (ret == QIO_CHANNEL_ERR_BLOCK) {
667             ret = 0;
668         } else {
669             tcp_chr_disconnect(chr);
670             goto end;
671         }
672     }
673     init->buflen -= ret;
674 
675     if (init->buflen == 0) {
676         tcp_chr_connect(chr);
677         goto end;
678     }
679 
680     memmove(init->buf, init->buf + ret, init->buflen);
681 
682     return G_SOURCE_CONTINUE;
683 
684 end:
685     g_free(s->telnet_init);
686     s->telnet_init = NULL;
687     g_source_unref(s->telnet_source);
688     s->telnet_source = NULL;
689     return G_SOURCE_REMOVE;
690 }
691 
692 static void tcp_chr_telnet_init(Chardev *chr)
693 {
694     SocketChardev *s = SOCKET_CHARDEV(chr);
695     TCPChardevTelnetInit *init;
696     size_t n = 0;
697 
698     /* Destroy existing task */
699     tcp_chr_telnet_destroy(s);
700 
701     if (s->telnet_init) {
702         /* We are possibly during a handshake already */
703         goto cont;
704     }
705 
706     s->telnet_init = g_new0(TCPChardevTelnetInit, 1);
707     init = s->telnet_init;
708 
709 #define IACSET(x, a, b, c)                      \
710     do {                                        \
711         x[n++] = a;                             \
712         x[n++] = b;                             \
713         x[n++] = c;                             \
714     } while (0)
715 
716     if (!s->is_tn3270) {
717         init->buflen = 12;
718         /* Prep the telnet negotion to put telnet in binary,
719          * no echo, single char mode */
720         IACSET(init->buf, 0xff, 0xfb, 0x01);  /* IAC WILL ECHO */
721         IACSET(init->buf, 0xff, 0xfb, 0x03);  /* IAC WILL Suppress go ahead */
722         IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL Binary */
723         IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO Binary */
724     } else {
725         init->buflen = 21;
726         /* Prep the TN3270 negotion based on RFC1576 */
727         IACSET(init->buf, 0xff, 0xfd, 0x19);  /* IAC DO EOR */
728         IACSET(init->buf, 0xff, 0xfb, 0x19);  /* IAC WILL EOR */
729         IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO BINARY */
730         IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL BINARY */
731         IACSET(init->buf, 0xff, 0xfd, 0x18);  /* IAC DO TERMINAL TYPE */
732         IACSET(init->buf, 0xff, 0xfa, 0x18);  /* IAC SB TERMINAL TYPE */
733         IACSET(init->buf, 0x01, 0xff, 0xf0);  /* SEND IAC SE */
734     }
735 
736 #undef IACSET
737 
738 cont:
739     s->telnet_source = qio_channel_add_watch_source(s->ioc, G_IO_OUT,
740                                                     tcp_chr_telnet_init_io,
741                                                     s, NULL,
742                                                     chr->gcontext);
743 }
744 
745 
746 static void tcp_chr_websock_handshake(QIOTask *task, gpointer user_data)
747 {
748     Chardev *chr = user_data;
749     SocketChardev *s = user_data;
750 
751     if (qio_task_propagate_error(task, NULL)) {
752         tcp_chr_disconnect(chr);
753     } else {
754         if (s->do_telnetopt) {
755             tcp_chr_telnet_init(chr);
756         } else {
757             tcp_chr_connect(chr);
758         }
759     }
760 }
761 
762 
763 static void tcp_chr_websock_init(Chardev *chr)
764 {
765     SocketChardev *s = SOCKET_CHARDEV(chr);
766     QIOChannelWebsock *wioc = NULL;
767     gchar *name;
768 
769     wioc = qio_channel_websock_new_server(s->ioc);
770 
771     name = g_strdup_printf("chardev-websocket-server-%s", chr->label);
772     qio_channel_set_name(QIO_CHANNEL(wioc), name);
773     g_free(name);
774     object_unref(OBJECT(s->ioc));
775     s->ioc = QIO_CHANNEL(wioc);
776 
777     qio_channel_websock_handshake(wioc, tcp_chr_websock_handshake, chr, NULL);
778 }
779 
780 
781 static void tcp_chr_tls_handshake(QIOTask *task,
782                                   gpointer user_data)
783 {
784     Chardev *chr = user_data;
785     SocketChardev *s = user_data;
786 
787     if (qio_task_propagate_error(task, NULL)) {
788         tcp_chr_disconnect(chr);
789     } else {
790         if (s->is_websock) {
791             tcp_chr_websock_init(chr);
792         } else if (s->do_telnetopt) {
793             tcp_chr_telnet_init(chr);
794         } else {
795             tcp_chr_connect(chr);
796         }
797     }
798 }
799 
800 
801 static void tcp_chr_tls_init(Chardev *chr)
802 {
803     SocketChardev *s = SOCKET_CHARDEV(chr);
804     QIOChannelTLS *tioc;
805     Error *err = NULL;
806     gchar *name;
807 
808     if (s->is_listen) {
809         tioc = qio_channel_tls_new_server(
810             s->ioc, s->tls_creds,
811             s->tls_authz,
812             &err);
813     } else {
814         tioc = qio_channel_tls_new_client(
815             s->ioc, s->tls_creds,
816             s->addr->u.inet.host,
817             &err);
818     }
819     if (tioc == NULL) {
820         error_free(err);
821         tcp_chr_disconnect(chr);
822         return;
823     }
824     name = g_strdup_printf("chardev-tls-%s-%s",
825                            s->is_listen ? "server" : "client",
826                            chr->label);
827     qio_channel_set_name(QIO_CHANNEL(tioc), name);
828     g_free(name);
829     object_unref(OBJECT(s->ioc));
830     s->ioc = QIO_CHANNEL(tioc);
831 
832     qio_channel_tls_handshake(tioc,
833                               tcp_chr_tls_handshake,
834                               chr,
835                               NULL,
836                               chr->gcontext);
837 }
838 
839 
840 static void tcp_chr_set_client_ioc_name(Chardev *chr,
841                                         QIOChannelSocket *sioc)
842 {
843     SocketChardev *s = SOCKET_CHARDEV(chr);
844     char *name;
845     name = g_strdup_printf("chardev-tcp-%s-%s",
846                            s->is_listen ? "server" : "client",
847                            chr->label);
848     qio_channel_set_name(QIO_CHANNEL(sioc), name);
849     g_free(name);
850 
851 }
852 
853 static int tcp_chr_new_client(Chardev *chr, QIOChannelSocket *sioc)
854 {
855     SocketChardev *s = SOCKET_CHARDEV(chr);
856 
857     if (s->state != TCP_CHARDEV_STATE_CONNECTING) {
858         return -1;
859     }
860 
861     s->ioc = QIO_CHANNEL(sioc);
862     object_ref(OBJECT(sioc));
863     s->sioc = sioc;
864     object_ref(OBJECT(sioc));
865 
866     qio_channel_set_blocking(s->ioc, false, NULL);
867 
868     if (s->do_nodelay) {
869         qio_channel_set_delay(s->ioc, false);
870     }
871     if (s->listener) {
872         qio_net_listener_set_client_func_full(s->listener, NULL, NULL,
873                                               NULL, chr->gcontext);
874     }
875 
876     if (s->tls_creds) {
877         tcp_chr_tls_init(chr);
878     } else if (s->is_websock) {
879         tcp_chr_websock_init(chr);
880     } else if (s->do_telnetopt) {
881         tcp_chr_telnet_init(chr);
882     } else {
883         tcp_chr_connect(chr);
884     }
885 
886     return 0;
887 }
888 
889 
890 static int tcp_chr_add_client(Chardev *chr, int fd)
891 {
892     int ret;
893     QIOChannelSocket *sioc;
894     SocketChardev *s = SOCKET_CHARDEV(chr);
895 
896     if (s->state != TCP_CHARDEV_STATE_DISCONNECTED) {
897         return -1;
898     }
899 
900     sioc = qio_channel_socket_new_fd(fd, NULL);
901     if (!sioc) {
902         return -1;
903     }
904     tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING);
905     tcp_chr_set_client_ioc_name(chr, sioc);
906     ret = tcp_chr_new_client(chr, sioc);
907     object_unref(OBJECT(sioc));
908     return ret;
909 }
910 
911 static void tcp_chr_accept(QIONetListener *listener,
912                            QIOChannelSocket *cioc,
913                            void *opaque)
914 {
915     Chardev *chr = CHARDEV(opaque);
916     SocketChardev *s = SOCKET_CHARDEV(chr);
917 
918     tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING);
919     tcp_chr_set_client_ioc_name(chr, cioc);
920     tcp_chr_new_client(chr, cioc);
921 }
922 
923 
924 static int tcp_chr_connect_client_sync(Chardev *chr, Error **errp)
925 {
926     SocketChardev *s = SOCKET_CHARDEV(chr);
927     QIOChannelSocket *sioc = qio_channel_socket_new();
928     tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING);
929     tcp_chr_set_client_ioc_name(chr, sioc);
930     if (qio_channel_socket_connect_sync(sioc, s->addr, errp) < 0) {
931         tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED);
932         object_unref(OBJECT(sioc));
933         return -1;
934     }
935     tcp_chr_new_client(chr, sioc);
936     object_unref(OBJECT(sioc));
937     return 0;
938 }
939 
940 
941 static void tcp_chr_accept_server_sync(Chardev *chr)
942 {
943     SocketChardev *s = SOCKET_CHARDEV(chr);
944     QIOChannelSocket *sioc;
945     info_report("QEMU waiting for connection on: %s",
946                 chr->filename);
947     tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING);
948     sioc = qio_net_listener_wait_client(s->listener);
949     tcp_chr_set_client_ioc_name(chr, sioc);
950     tcp_chr_new_client(chr, sioc);
951     object_unref(OBJECT(sioc));
952 }
953 
954 
955 static int tcp_chr_wait_connected(Chardev *chr, Error **errp)
956 {
957     SocketChardev *s = SOCKET_CHARDEV(chr);
958     const char *opts[] = { "telnet", "tn3270", "websock", "tls-creds" };
959     bool optset[] = { s->is_telnet, s->is_tn3270, s->is_websock, s->tls_creds };
960     size_t i;
961 
962     QEMU_BUILD_BUG_ON(G_N_ELEMENTS(opts) != G_N_ELEMENTS(optset));
963     for (i = 0; i < G_N_ELEMENTS(opts); i++) {
964         if (optset[i]) {
965             error_setg(errp,
966                        "'%s' option is incompatible with waiting for "
967                        "connection completion", opts[i]);
968             return -1;
969         }
970     }
971 
972     tcp_chr_reconn_timer_cancel(s);
973 
974     /*
975      * We expect states to be as follows:
976      *
977      *  - server
978      *    - wait   -> CONNECTED
979      *    - nowait -> DISCONNECTED
980      *  - client
981      *    - reconnect == 0 -> CONNECTED
982      *    - reconnect != 0 -> CONNECTING
983      *
984      */
985     if (s->state == TCP_CHARDEV_STATE_CONNECTING) {
986         if (!s->connect_task) {
987             error_setg(errp,
988                        "Unexpected 'connecting' state without connect task "
989                        "while waiting for connection completion");
990             return -1;
991         }
992         /*
993          * tcp_chr_wait_connected should only ever be run from the
994          * main loop thread associated with chr->gcontext, otherwise
995          * qio_task_wait_thread has a dangerous race condition with
996          * free'ing of the s->connect_task object.
997          *
998          * Acquiring the main context doesn't 100% prove we're in
999          * the main loop thread, but it does at least guarantee
1000          * that the main loop won't be executed by another thread
1001          * avoiding the race condition with the task idle callback.
1002          */
1003         g_main_context_acquire(chr->gcontext);
1004         qio_task_wait_thread(s->connect_task);
1005         g_main_context_release(chr->gcontext);
1006 
1007         /*
1008          * The completion callback (qemu_chr_socket_connected) for
1009          * s->connect_task should have set this to NULL by the time
1010          * qio_task_wait_thread has returned.
1011          */
1012         assert(!s->connect_task);
1013 
1014         /*
1015          * NB we are *not* guaranteed to have "s->state == ..CONNECTED"
1016          * at this point as this first connect may be failed, so
1017          * allow the next loop to run regardless.
1018          */
1019     }
1020 
1021     while (s->state != TCP_CHARDEV_STATE_CONNECTED) {
1022         if (s->is_listen) {
1023             tcp_chr_accept_server_sync(chr);
1024         } else {
1025             Error *err = NULL;
1026             if (tcp_chr_connect_client_sync(chr, &err) < 0) {
1027                 if (s->reconnect_time) {
1028                     error_free(err);
1029                     g_usleep(s->reconnect_time * 1000ULL * 1000ULL);
1030                 } else {
1031                     error_propagate(errp, err);
1032                     return -1;
1033                 }
1034             }
1035         }
1036     }
1037 
1038     return 0;
1039 }
1040 
1041 static void char_socket_finalize(Object *obj)
1042 {
1043     Chardev *chr = CHARDEV(obj);
1044     SocketChardev *s = SOCKET_CHARDEV(obj);
1045 
1046     tcp_chr_free_connection(chr);
1047     tcp_chr_reconn_timer_cancel(s);
1048     qapi_free_SocketAddress(s->addr);
1049     tcp_chr_telnet_destroy(s);
1050     g_free(s->telnet_init);
1051     if (s->listener) {
1052         qio_net_listener_set_client_func_full(s->listener, NULL, NULL,
1053                                               NULL, chr->gcontext);
1054         object_unref(OBJECT(s->listener));
1055     }
1056     if (s->tls_creds) {
1057         object_unref(OBJECT(s->tls_creds));
1058     }
1059     g_free(s->tls_authz);
1060 
1061     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
1062 }
1063 
1064 static void qemu_chr_socket_connected(QIOTask *task, void *opaque)
1065 {
1066     QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
1067     Chardev *chr = CHARDEV(opaque);
1068     SocketChardev *s = SOCKET_CHARDEV(chr);
1069     Error *err = NULL;
1070 
1071     s->connect_task = NULL;
1072 
1073     if (qio_task_propagate_error(task, &err)) {
1074         tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED);
1075         check_report_connect_error(chr, err);
1076         error_free(err);
1077         goto cleanup;
1078     }
1079 
1080     s->connect_err_reported = false;
1081     tcp_chr_new_client(chr, sioc);
1082 
1083 cleanup:
1084     object_unref(OBJECT(sioc));
1085 }
1086 
1087 
1088 static void tcp_chr_connect_client_task(QIOTask *task,
1089                                         gpointer opaque)
1090 {
1091     QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
1092     SocketAddress *addr = opaque;
1093     Error *err = NULL;
1094 
1095     qio_channel_socket_connect_sync(ioc, addr, &err);
1096 
1097     qio_task_set_error(task, err);
1098 }
1099 
1100 
1101 static void tcp_chr_connect_client_async(Chardev *chr)
1102 {
1103     SocketChardev *s = SOCKET_CHARDEV(chr);
1104     QIOChannelSocket *sioc;
1105 
1106     tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING);
1107     sioc = qio_channel_socket_new();
1108     tcp_chr_set_client_ioc_name(chr, sioc);
1109     /*
1110      * Normally code would use the qio_channel_socket_connect_async
1111      * method which uses a QIOTask + qio_task_set_error internally
1112      * to avoid blocking. The tcp_chr_wait_connected method, however,
1113      * needs a way to synchronize with completion of the background
1114      * connect task which can't be done with the QIOChannelSocket
1115      * async APIs. Thus we must use QIOTask directly to implement
1116      * the non-blocking concept locally.
1117      */
1118     s->connect_task = qio_task_new(OBJECT(sioc),
1119                                    qemu_chr_socket_connected,
1120                                    chr, NULL);
1121     qio_task_run_in_thread(s->connect_task,
1122                            tcp_chr_connect_client_task,
1123                            s->addr,
1124                            NULL,
1125                            chr->gcontext);
1126 }
1127 
1128 static gboolean socket_reconnect_timeout(gpointer opaque)
1129 {
1130     Chardev *chr = CHARDEV(opaque);
1131     SocketChardev *s = SOCKET_CHARDEV(opaque);
1132 
1133     g_source_unref(s->reconnect_timer);
1134     s->reconnect_timer = NULL;
1135 
1136     if (chr->be_open) {
1137         return false;
1138     }
1139 
1140     tcp_chr_connect_client_async(chr);
1141 
1142     return false;
1143 }
1144 
1145 
1146 static int qmp_chardev_open_socket_server(Chardev *chr,
1147                                           bool is_telnet,
1148                                           bool is_waitconnect,
1149                                           Error **errp)
1150 {
1151     SocketChardev *s = SOCKET_CHARDEV(chr);
1152     char *name;
1153     if (is_telnet) {
1154         s->do_telnetopt = 1;
1155     }
1156     s->listener = qio_net_listener_new();
1157 
1158     name = g_strdup_printf("chardev-tcp-listener-%s", chr->label);
1159     qio_net_listener_set_name(s->listener, name);
1160     g_free(name);
1161 
1162     if (qio_net_listener_open_sync(s->listener, s->addr, errp) < 0) {
1163         object_unref(OBJECT(s->listener));
1164         s->listener = NULL;
1165         return -1;
1166     }
1167 
1168     qapi_free_SocketAddress(s->addr);
1169     s->addr = socket_local_address(s->listener->sioc[0]->fd, errp);
1170     update_disconnected_filename(s);
1171 
1172     if (is_waitconnect) {
1173         tcp_chr_accept_server_sync(chr);
1174     } else {
1175         qio_net_listener_set_client_func_full(s->listener,
1176                                               tcp_chr_accept,
1177                                               chr, NULL,
1178                                               chr->gcontext);
1179     }
1180 
1181     return 0;
1182 }
1183 
1184 
1185 static int qmp_chardev_open_socket_client(Chardev *chr,
1186                                           int64_t reconnect,
1187                                           Error **errp)
1188 {
1189     SocketChardev *s = SOCKET_CHARDEV(chr);
1190 
1191     if (reconnect > 0) {
1192         s->reconnect_time = reconnect;
1193         tcp_chr_connect_client_async(chr);
1194         return 0;
1195     } else {
1196         return tcp_chr_connect_client_sync(chr, errp);
1197     }
1198 }
1199 
1200 
1201 static bool qmp_chardev_validate_socket(ChardevSocket *sock,
1202                                         SocketAddress *addr,
1203                                         Error **errp)
1204 {
1205     /* Validate any options which have a dependency on address type */
1206     switch (addr->type) {
1207     case SOCKET_ADDRESS_TYPE_FD:
1208         if (sock->has_reconnect) {
1209             error_setg(errp,
1210                        "'reconnect' option is incompatible with "
1211                        "'fd' address type");
1212             return false;
1213         }
1214         if (sock->has_tls_creds &&
1215             !(sock->has_server && sock->server)) {
1216             error_setg(errp,
1217                        "'tls_creds' option is incompatible with "
1218                        "'fd' address type as client");
1219             return false;
1220         }
1221         break;
1222 
1223     case SOCKET_ADDRESS_TYPE_UNIX:
1224         if (sock->has_tls_creds) {
1225             error_setg(errp,
1226                        "'tls_creds' option is incompatible with "
1227                        "'unix' address type");
1228             return false;
1229         }
1230         break;
1231 
1232     case SOCKET_ADDRESS_TYPE_INET:
1233         break;
1234 
1235     case SOCKET_ADDRESS_TYPE_VSOCK:
1236         if (sock->has_tls_creds) {
1237             error_setg(errp,
1238                        "'tls_creds' option is incompatible with "
1239                        "'vsock' address type");
1240             return false;
1241         }
1242 
1243     default:
1244         break;
1245     }
1246 
1247     if (sock->has_tls_authz && !sock->has_tls_creds) {
1248         error_setg(errp, "'tls_authz' option requires 'tls_creds' option");
1249         return false;
1250     }
1251 
1252     /* Validate any options which have a dependancy on client vs server */
1253     if (!sock->has_server || sock->server) {
1254         if (sock->has_reconnect) {
1255             error_setg(errp,
1256                        "'reconnect' option is incompatible with "
1257                        "socket in server listen mode");
1258             return false;
1259         }
1260     } else {
1261         if (sock->has_websocket && sock->websocket) {
1262             error_setg(errp, "%s", "Websocket client is not implemented");
1263             return false;
1264         }
1265         if (sock->has_wait) {
1266             warn_report("'wait' option is deprecated with "
1267                         "socket in client connect mode");
1268             if (sock->wait) {
1269                 error_setg(errp, "%s",
1270                            "'wait' option is incompatible with "
1271                            "socket in client connect mode");
1272                 return false;
1273             }
1274         }
1275     }
1276 
1277     return true;
1278 }
1279 
1280 
1281 static void qmp_chardev_open_socket(Chardev *chr,
1282                                     ChardevBackend *backend,
1283                                     bool *be_opened,
1284                                     Error **errp)
1285 {
1286     SocketChardev *s = SOCKET_CHARDEV(chr);
1287     ChardevSocket *sock = backend->u.socket.data;
1288     bool do_nodelay     = sock->has_nodelay ? sock->nodelay : false;
1289     bool is_listen      = sock->has_server  ? sock->server  : true;
1290     bool is_telnet      = sock->has_telnet  ? sock->telnet  : false;
1291     bool is_tn3270      = sock->has_tn3270  ? sock->tn3270  : false;
1292     bool is_waitconnect = sock->has_wait    ? sock->wait    : false;
1293     bool is_websock     = sock->has_websocket ? sock->websocket : false;
1294     int64_t reconnect   = sock->has_reconnect ? sock->reconnect : 0;
1295     SocketAddress *addr;
1296 
1297     s->is_listen = is_listen;
1298     s->is_telnet = is_telnet;
1299     s->is_tn3270 = is_tn3270;
1300     s->is_websock = is_websock;
1301     s->do_nodelay = do_nodelay;
1302     if (sock->tls_creds) {
1303         Object *creds;
1304         creds = object_resolve_path_component(
1305             object_get_objects_root(), sock->tls_creds);
1306         if (!creds) {
1307             error_setg(errp, "No TLS credentials with id '%s'",
1308                        sock->tls_creds);
1309             return;
1310         }
1311         s->tls_creds = (QCryptoTLSCreds *)
1312             object_dynamic_cast(creds,
1313                                 TYPE_QCRYPTO_TLS_CREDS);
1314         if (!s->tls_creds) {
1315             error_setg(errp, "Object with id '%s' is not TLS credentials",
1316                        sock->tls_creds);
1317             return;
1318         }
1319         object_ref(OBJECT(s->tls_creds));
1320         if (is_listen) {
1321             if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
1322                 error_setg(errp, "%s",
1323                            "Expected TLS credentials for server endpoint");
1324                 return;
1325             }
1326         } else {
1327             if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
1328                 error_setg(errp, "%s",
1329                            "Expected TLS credentials for client endpoint");
1330                 return;
1331             }
1332         }
1333     }
1334     s->tls_authz = g_strdup(sock->tls_authz);
1335 
1336     s->addr = addr = socket_address_flatten(sock->addr);
1337 
1338     if (!qmp_chardev_validate_socket(sock, addr, errp)) {
1339         return;
1340     }
1341 
1342     qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE);
1343     /* TODO SOCKET_ADDRESS_FD where fd has AF_UNIX */
1344     if (addr->type == SOCKET_ADDRESS_TYPE_UNIX) {
1345         qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_FD_PASS);
1346     }
1347 
1348     /* be isn't opened until we get a connection */
1349     *be_opened = false;
1350 
1351     update_disconnected_filename(s);
1352 
1353     if (s->is_listen) {
1354         if (qmp_chardev_open_socket_server(chr, is_telnet || is_tn3270,
1355                                            is_waitconnect, errp) < 0) {
1356             return;
1357         }
1358     } else {
1359         if (qmp_chardev_open_socket_client(chr, reconnect, errp) < 0) {
1360             return;
1361         }
1362     }
1363 }
1364 
1365 static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
1366                                   Error **errp)
1367 {
1368     const char *path = qemu_opt_get(opts, "path");
1369     const char *host = qemu_opt_get(opts, "host");
1370     const char *port = qemu_opt_get(opts, "port");
1371     const char *fd = qemu_opt_get(opts, "fd");
1372     SocketAddressLegacy *addr;
1373     ChardevSocket *sock;
1374 
1375     if ((!!path + !!fd + !!host) != 1) {
1376         error_setg(errp,
1377                    "Exactly one of 'path', 'fd' or 'host' required");
1378         return;
1379     }
1380 
1381     if (host && !port) {
1382         error_setg(errp, "chardev: socket: no port given");
1383         return;
1384     }
1385 
1386     backend->type = CHARDEV_BACKEND_KIND_SOCKET;
1387     sock = backend->u.socket.data = g_new0(ChardevSocket, 1);
1388     qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock));
1389 
1390     sock->has_nodelay = qemu_opt_get(opts, "delay");
1391     sock->nodelay = !qemu_opt_get_bool(opts, "delay", true);
1392     /*
1393      * We have different default to QMP for 'server', hence
1394      * we can't just check for existence of 'server'
1395      */
1396     sock->has_server = true;
1397     sock->server = qemu_opt_get_bool(opts, "server", false);
1398     sock->has_telnet = qemu_opt_get(opts, "telnet");
1399     sock->telnet = qemu_opt_get_bool(opts, "telnet", false);
1400     sock->has_tn3270 = qemu_opt_get(opts, "tn3270");
1401     sock->tn3270 = qemu_opt_get_bool(opts, "tn3270", false);
1402     sock->has_websocket = qemu_opt_get(opts, "websocket");
1403     sock->websocket = qemu_opt_get_bool(opts, "websocket", false);
1404     /*
1405      * We have different default to QMP for 'wait' when 'server'
1406      * is set, hence we can't just check for existence of 'wait'
1407      */
1408     sock->has_wait = qemu_opt_find(opts, "wait") || sock->server;
1409     sock->wait = qemu_opt_get_bool(opts, "wait", true);
1410     sock->has_reconnect = qemu_opt_find(opts, "reconnect");
1411     sock->reconnect = qemu_opt_get_number(opts, "reconnect", 0);
1412     sock->has_tls_creds = qemu_opt_get(opts, "tls-creds");
1413     sock->tls_creds = g_strdup(qemu_opt_get(opts, "tls-creds"));
1414     sock->has_tls_authz = qemu_opt_get(opts, "tls-authz");
1415     sock->tls_authz = g_strdup(qemu_opt_get(opts, "tls-authz"));
1416 
1417     addr = g_new0(SocketAddressLegacy, 1);
1418     if (path) {
1419         UnixSocketAddress *q_unix;
1420         addr->type = SOCKET_ADDRESS_LEGACY_KIND_UNIX;
1421         q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
1422         q_unix->path = g_strdup(path);
1423     } else if (host) {
1424         addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;
1425         addr->u.inet.data = g_new(InetSocketAddress, 1);
1426         *addr->u.inet.data = (InetSocketAddress) {
1427             .host = g_strdup(host),
1428             .port = g_strdup(port),
1429             .has_to = qemu_opt_get(opts, "to"),
1430             .to = qemu_opt_get_number(opts, "to", 0),
1431             .has_ipv4 = qemu_opt_get(opts, "ipv4"),
1432             .ipv4 = qemu_opt_get_bool(opts, "ipv4", 0),
1433             .has_ipv6 = qemu_opt_get(opts, "ipv6"),
1434             .ipv6 = qemu_opt_get_bool(opts, "ipv6", 0),
1435         };
1436     } else if (fd) {
1437         addr->type = SOCKET_ADDRESS_LEGACY_KIND_FD;
1438         addr->u.fd.data = g_new(String, 1);
1439         addr->u.fd.data->str = g_strdup(fd);
1440     } else {
1441         g_assert_not_reached();
1442     }
1443     sock->addr = addr;
1444 }
1445 
1446 static void
1447 char_socket_get_addr(Object *obj, Visitor *v, const char *name,
1448                      void *opaque, Error **errp)
1449 {
1450     SocketChardev *s = SOCKET_CHARDEV(obj);
1451 
1452     visit_type_SocketAddress(v, name, &s->addr, errp);
1453 }
1454 
1455 static bool
1456 char_socket_get_connected(Object *obj, Error **errp)
1457 {
1458     SocketChardev *s = SOCKET_CHARDEV(obj);
1459 
1460     return s->state == TCP_CHARDEV_STATE_CONNECTED;
1461 }
1462 
1463 static void char_socket_class_init(ObjectClass *oc, void *data)
1464 {
1465     ChardevClass *cc = CHARDEV_CLASS(oc);
1466 
1467     cc->parse = qemu_chr_parse_socket;
1468     cc->open = qmp_chardev_open_socket;
1469     cc->chr_wait_connected = tcp_chr_wait_connected;
1470     cc->chr_write = tcp_chr_write;
1471     cc->chr_sync_read = tcp_chr_sync_read;
1472     cc->chr_disconnect = tcp_chr_disconnect;
1473     cc->get_msgfds = tcp_get_msgfds;
1474     cc->set_msgfds = tcp_set_msgfds;
1475     cc->chr_add_client = tcp_chr_add_client;
1476     cc->chr_add_watch = tcp_chr_add_watch;
1477     cc->chr_update_read_handler = tcp_chr_update_read_handler;
1478 
1479     object_class_property_add(oc, "addr", "SocketAddress",
1480                               char_socket_get_addr, NULL,
1481                               NULL, NULL, &error_abort);
1482 
1483     object_class_property_add_bool(oc, "connected", char_socket_get_connected,
1484                                    NULL, &error_abort);
1485 }
1486 
1487 static const TypeInfo char_socket_type_info = {
1488     .name = TYPE_CHARDEV_SOCKET,
1489     .parent = TYPE_CHARDEV,
1490     .instance_size = sizeof(SocketChardev),
1491     .instance_finalize = char_socket_finalize,
1492     .class_init = char_socket_class_init,
1493 };
1494 
1495 static void register_types(void)
1496 {
1497     type_register_static(&char_socket_type_info);
1498 }
1499 
1500 type_init(register_types);
1501