xref: /openbmc/qemu/chardev/char-socket.c (revision 429d3ae2)
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/net-listener.h"
30 #include "qemu/error-report.h"
31 #include "qemu/option.h"
32 #include "qapi/error.h"
33 #include "qapi/clone-visitor.h"
34 #include "qapi/qapi-visit-sockets.h"
35 #include "sysemu/sysemu.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 struct {
50     Chardev parent;
51     QIOChannel *ioc; /* Client I/O channel */
52     QIOChannelSocket *sioc; /* Client master channel */
53     QIONetListener *listener;
54     GSource *hup_source;
55     QCryptoTLSCreds *tls_creds;
56     int connected;
57     int max_size;
58     int do_telnetopt;
59     int do_nodelay;
60     int *read_msgfds;
61     size_t read_msgfds_num;
62     int *write_msgfds;
63     size_t write_msgfds_num;
64 
65     SocketAddress *addr;
66     bool is_listen;
67     bool is_telnet;
68     bool is_tn3270;
69     GSource *telnet_source;
70     TCPChardevTelnetInit *telnet_init;
71 
72     GSource *reconnect_timer;
73     int64_t reconnect_time;
74     bool connect_err_reported;
75 } SocketChardev;
76 
77 #define SOCKET_CHARDEV(obj)                                     \
78     OBJECT_CHECK(SocketChardev, (obj), TYPE_CHARDEV_SOCKET)
79 
80 static gboolean socket_reconnect_timeout(gpointer opaque);
81 static void tcp_chr_telnet_init(Chardev *chr);
82 
83 static void tcp_chr_reconn_timer_cancel(SocketChardev *s)
84 {
85     if (s->reconnect_timer) {
86         g_source_destroy(s->reconnect_timer);
87         g_source_unref(s->reconnect_timer);
88         s->reconnect_timer = NULL;
89     }
90 }
91 
92 static void qemu_chr_socket_restart_timer(Chardev *chr)
93 {
94     SocketChardev *s = SOCKET_CHARDEV(chr);
95     char *name;
96 
97     assert(s->connected == 0);
98     name = g_strdup_printf("chardev-socket-reconnect-%s", chr->label);
99     s->reconnect_timer = qemu_chr_timeout_add_ms(chr,
100                                                  s->reconnect_time * 1000,
101                                                  socket_reconnect_timeout,
102                                                  chr);
103     g_source_set_name(s->reconnect_timer, name);
104     g_free(name);
105 }
106 
107 static void check_report_connect_error(Chardev *chr,
108                                        Error *err)
109 {
110     SocketChardev *s = SOCKET_CHARDEV(chr);
111 
112     if (!s->connect_err_reported) {
113         error_report("Unable to connect character device %s: %s",
114                      chr->label, error_get_pretty(err));
115         s->connect_err_reported = true;
116     }
117     qemu_chr_socket_restart_timer(chr);
118 }
119 
120 static void tcp_chr_accept(QIONetListener *listener,
121                            QIOChannelSocket *cioc,
122                            void *opaque);
123 
124 static int tcp_chr_read_poll(void *opaque);
125 static void tcp_chr_disconnect(Chardev *chr);
126 
127 /* Called with chr_write_lock held.  */
128 static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len)
129 {
130     SocketChardev *s = SOCKET_CHARDEV(chr);
131 
132     if (s->connected) {
133         int ret =  io_channel_send_full(s->ioc, buf, len,
134                                         s->write_msgfds,
135                                         s->write_msgfds_num);
136 
137         /* free the written msgfds in any cases other than errno==EAGAIN */
138         if (EAGAIN != errno && s->write_msgfds_num) {
139             g_free(s->write_msgfds);
140             s->write_msgfds = 0;
141             s->write_msgfds_num = 0;
142         }
143 
144         if (ret < 0 && errno != EAGAIN) {
145             if (tcp_chr_read_poll(chr) <= 0) {
146                 tcp_chr_disconnect(chr);
147                 return len;
148             } /* else let the read handler finish it properly */
149         }
150 
151         return ret;
152     } else {
153         /* XXX: indicate an error ? */
154         return len;
155     }
156 }
157 
158 static int tcp_chr_read_poll(void *opaque)
159 {
160     Chardev *chr = CHARDEV(opaque);
161     SocketChardev *s = SOCKET_CHARDEV(opaque);
162     if (!s->connected) {
163         return 0;
164     }
165     s->max_size = qemu_chr_be_can_write(chr);
166     return s->max_size;
167 }
168 
169 static void tcp_chr_process_IAC_bytes(Chardev *chr,
170                                       SocketChardev *s,
171                                       uint8_t *buf, int *size)
172 {
173     /* Handle any telnet or tn3270 client's basic IAC options.
174      * For telnet options, it satisfies char by char mode with no echo.
175      * For tn3270 options, it satisfies binary mode with EOR.
176      * All IAC options will be removed from the buf and the do_opt
177      * pointer will be used to track the state of the width of the
178      * IAC information.
179      *
180      * RFC854: "All TELNET commands consist of at least a two byte sequence.
181      * The commands dealing with option negotiation are three byte sequences,
182      * the third byte being the code for the option referenced."
183      * "IAC BREAK", "IAC IP", "IAC NOP" and the double IAC are two bytes.
184      * "IAC SB", "IAC SE" and "IAC EOR" are saved to split up data boundary
185      * for tn3270.
186      * NOP, Break and Interrupt Process(IP) might be encountered during a TN3270
187      * session, and NOP and IP need to be done later.
188      */
189 
190     int i;
191     int j = 0;
192 
193     for (i = 0; i < *size; i++) {
194         if (s->do_telnetopt > 1) {
195             if ((unsigned char)buf[i] == IAC && s->do_telnetopt == 2) {
196                 /* Double IAC means send an IAC */
197                 if (j != i) {
198                     buf[j] = buf[i];
199                 }
200                 j++;
201                 s->do_telnetopt = 1;
202             } else {
203                 if ((unsigned char)buf[i] == IAC_BREAK
204                     && s->do_telnetopt == 2) {
205                     /* Handle IAC break commands by sending a serial break */
206                     qemu_chr_be_event(chr, CHR_EVENT_BREAK);
207                     s->do_telnetopt++;
208                 } else if (s->is_tn3270 && ((unsigned char)buf[i] == IAC_EOR
209                            || (unsigned char)buf[i] == IAC_SB
210                            || (unsigned char)buf[i] == IAC_SE)
211                            && s->do_telnetopt == 2) {
212                     buf[j++] = IAC;
213                     buf[j++] = buf[i];
214                     s->do_telnetopt++;
215                 } else if (s->is_tn3270 && ((unsigned char)buf[i] == IAC_IP
216                            || (unsigned char)buf[i] == IAC_NOP)
217                            && s->do_telnetopt == 2) {
218                     /* TODO: IP and NOP need to be implemented later. */
219                     s->do_telnetopt++;
220                 }
221                 s->do_telnetopt++;
222             }
223             if (s->do_telnetopt >= 4) {
224                 s->do_telnetopt = 1;
225             }
226         } else {
227             if ((unsigned char)buf[i] == IAC) {
228                 s->do_telnetopt = 2;
229             } else {
230                 if (j != i) {
231                     buf[j] = buf[i];
232                 }
233                 j++;
234             }
235         }
236     }
237     *size = j;
238 }
239 
240 static int tcp_get_msgfds(Chardev *chr, int *fds, int num)
241 {
242     SocketChardev *s = SOCKET_CHARDEV(chr);
243 
244     int to_copy = (s->read_msgfds_num < num) ? s->read_msgfds_num : num;
245 
246     assert(num <= TCP_MAX_FDS);
247 
248     if (to_copy) {
249         int i;
250 
251         memcpy(fds, s->read_msgfds, to_copy * sizeof(int));
252 
253         /* Close unused fds */
254         for (i = to_copy; i < s->read_msgfds_num; i++) {
255             close(s->read_msgfds[i]);
256         }
257 
258         g_free(s->read_msgfds);
259         s->read_msgfds = 0;
260         s->read_msgfds_num = 0;
261     }
262 
263     return to_copy;
264 }
265 
266 static int tcp_set_msgfds(Chardev *chr, int *fds, int num)
267 {
268     SocketChardev *s = SOCKET_CHARDEV(chr);
269 
270     /* clear old pending fd array */
271     g_free(s->write_msgfds);
272     s->write_msgfds = NULL;
273     s->write_msgfds_num = 0;
274 
275     if (!s->connected ||
276         !qio_channel_has_feature(s->ioc,
277                                  QIO_CHANNEL_FEATURE_FD_PASS)) {
278         return -1;
279     }
280 
281     if (num) {
282         s->write_msgfds = g_new(int, num);
283         memcpy(s->write_msgfds, fds, num * sizeof(int));
284     }
285 
286     s->write_msgfds_num = num;
287 
288     return 0;
289 }
290 
291 static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len)
292 {
293     SocketChardev *s = SOCKET_CHARDEV(chr);
294     struct iovec iov = { .iov_base = buf, .iov_len = len };
295     int ret;
296     size_t i;
297     int *msgfds = NULL;
298     size_t msgfds_num = 0;
299 
300     if (qio_channel_has_feature(s->ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
301         ret = qio_channel_readv_full(s->ioc, &iov, 1,
302                                      &msgfds, &msgfds_num,
303                                      NULL);
304     } else {
305         ret = qio_channel_readv_full(s->ioc, &iov, 1,
306                                      NULL, NULL,
307                                      NULL);
308     }
309 
310     if (ret == QIO_CHANNEL_ERR_BLOCK) {
311         errno = EAGAIN;
312         ret = -1;
313     } else if (ret == -1) {
314         errno = EIO;
315     }
316 
317     if (msgfds_num) {
318         /* close and clean read_msgfds */
319         for (i = 0; i < s->read_msgfds_num; i++) {
320             close(s->read_msgfds[i]);
321         }
322 
323         if (s->read_msgfds_num) {
324             g_free(s->read_msgfds);
325         }
326 
327         s->read_msgfds = msgfds;
328         s->read_msgfds_num = msgfds_num;
329     }
330 
331     for (i = 0; i < s->read_msgfds_num; i++) {
332         int fd = s->read_msgfds[i];
333         if (fd < 0) {
334             continue;
335         }
336 
337         /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
338         qemu_set_block(fd);
339 
340 #ifndef MSG_CMSG_CLOEXEC
341         qemu_set_cloexec(fd);
342 #endif
343     }
344 
345     return ret;
346 }
347 
348 static GSource *tcp_chr_add_watch(Chardev *chr, GIOCondition cond)
349 {
350     SocketChardev *s = SOCKET_CHARDEV(chr);
351     return qio_channel_create_watch(s->ioc, cond);
352 }
353 
354 static void tcp_chr_free_connection(Chardev *chr)
355 {
356     SocketChardev *s = SOCKET_CHARDEV(chr);
357     int i;
358 
359     if (s->read_msgfds_num) {
360         for (i = 0; i < s->read_msgfds_num; i++) {
361             close(s->read_msgfds[i]);
362         }
363         g_free(s->read_msgfds);
364         s->read_msgfds = NULL;
365         s->read_msgfds_num = 0;
366     }
367 
368     if (s->hup_source != NULL) {
369         g_source_destroy(s->hup_source);
370         g_source_unref(s->hup_source);
371         s->hup_source = NULL;
372     }
373 
374     tcp_set_msgfds(chr, NULL, 0);
375     remove_fd_in_watch(chr);
376     object_unref(OBJECT(s->sioc));
377     s->sioc = NULL;
378     object_unref(OBJECT(s->ioc));
379     s->ioc = NULL;
380     g_free(chr->filename);
381     chr->filename = NULL;
382     s->connected = 0;
383 }
384 
385 static char *SocketAddress_to_str(const char *prefix, SocketAddress *addr,
386                                   bool is_listen, bool is_telnet)
387 {
388     switch (addr->type) {
389     case SOCKET_ADDRESS_TYPE_INET:
390         return g_strdup_printf("%s%s:%s:%s%s", prefix,
391                                is_telnet ? "telnet" : "tcp",
392                                addr->u.inet.host,
393                                addr->u.inet.port,
394                                is_listen ? ",server" : "");
395         break;
396     case SOCKET_ADDRESS_TYPE_UNIX:
397         return g_strdup_printf("%sunix:%s%s", prefix,
398                                addr->u.q_unix.path,
399                                is_listen ? ",server" : "");
400         break;
401     case SOCKET_ADDRESS_TYPE_FD:
402         return g_strdup_printf("%sfd:%s%s", prefix, addr->u.fd.str,
403                                is_listen ? ",server" : "");
404         break;
405     case SOCKET_ADDRESS_TYPE_VSOCK:
406         return g_strdup_printf("%svsock:%s:%s", prefix,
407                                addr->u.vsock.cid,
408                                addr->u.vsock.port);
409     default:
410         abort();
411     }
412 }
413 
414 static void update_disconnected_filename(SocketChardev *s)
415 {
416     Chardev *chr = CHARDEV(s);
417 
418     g_free(chr->filename);
419     chr->filename = SocketAddress_to_str("disconnected:", s->addr,
420                                          s->is_listen, s->is_telnet);
421 }
422 
423 /* NB may be called even if tcp_chr_connect has not been
424  * reached, due to TLS or telnet initialization failure,
425  * so can *not* assume s->connected == true
426  */
427 static void tcp_chr_disconnect(Chardev *chr)
428 {
429     SocketChardev *s = SOCKET_CHARDEV(chr);
430     bool emit_close = s->connected;
431 
432     tcp_chr_free_connection(chr);
433 
434     if (s->listener) {
435         qio_net_listener_set_client_func_full(s->listener, tcp_chr_accept,
436                                               chr, NULL, chr->gcontext);
437     }
438     update_disconnected_filename(s);
439     if (emit_close) {
440         qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
441     }
442     if (s->reconnect_time) {
443         qemu_chr_socket_restart_timer(chr);
444     }
445 }
446 
447 static gboolean tcp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
448 {
449     Chardev *chr = CHARDEV(opaque);
450     SocketChardev *s = SOCKET_CHARDEV(opaque);
451     uint8_t buf[CHR_READ_BUF_LEN];
452     int len, size;
453 
454     if (!s->connected || s->max_size <= 0) {
455         return TRUE;
456     }
457     len = sizeof(buf);
458     if (len > s->max_size) {
459         len = s->max_size;
460     }
461     size = tcp_chr_recv(chr, (void *)buf, len);
462     if (size == 0 || (size == -1 && errno != EAGAIN)) {
463         /* connection closed */
464         tcp_chr_disconnect(chr);
465     } else if (size > 0) {
466         if (s->do_telnetopt) {
467             tcp_chr_process_IAC_bytes(chr, s, buf, &size);
468         }
469         if (size > 0) {
470             qemu_chr_be_write(chr, buf, size);
471         }
472     }
473 
474     return TRUE;
475 }
476 
477 static gboolean tcp_chr_hup(QIOChannel *channel,
478                                GIOCondition cond,
479                                void *opaque)
480 {
481     Chardev *chr = CHARDEV(opaque);
482     tcp_chr_disconnect(chr);
483     return G_SOURCE_REMOVE;
484 }
485 
486 static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len)
487 {
488     SocketChardev *s = SOCKET_CHARDEV(chr);
489     int size;
490 
491     if (!s->connected) {
492         return 0;
493     }
494 
495     qio_channel_set_blocking(s->ioc, true, NULL);
496     size = tcp_chr_recv(chr, (void *) buf, len);
497     qio_channel_set_blocking(s->ioc, false, NULL);
498     if (size == 0) {
499         /* connection closed */
500         tcp_chr_disconnect(chr);
501     }
502 
503     return size;
504 }
505 
506 static char *sockaddr_to_str(struct sockaddr_storage *ss, socklen_t ss_len,
507                              struct sockaddr_storage *ps, socklen_t ps_len,
508                              bool is_listen, bool is_telnet)
509 {
510     char shost[NI_MAXHOST], sserv[NI_MAXSERV];
511     char phost[NI_MAXHOST], pserv[NI_MAXSERV];
512     const char *left = "", *right = "";
513 
514     switch (ss->ss_family) {
515 #ifndef _WIN32
516     case AF_UNIX:
517         return g_strdup_printf("unix:%s%s",
518                                ((struct sockaddr_un *)(ss))->sun_path,
519                                is_listen ? ",server" : "");
520 #endif
521     case AF_INET6:
522         left  = "[";
523         right = "]";
524         /* fall through */
525     case AF_INET:
526         getnameinfo((struct sockaddr *) ss, ss_len, shost, sizeof(shost),
527                     sserv, sizeof(sserv), NI_NUMERICHOST | NI_NUMERICSERV);
528         getnameinfo((struct sockaddr *) ps, ps_len, phost, sizeof(phost),
529                     pserv, sizeof(pserv), NI_NUMERICHOST | NI_NUMERICSERV);
530         return g_strdup_printf("%s:%s%s%s:%s%s <-> %s%s%s:%s",
531                                is_telnet ? "telnet" : "tcp",
532                                left, shost, right, sserv,
533                                is_listen ? ",server" : "",
534                                left, phost, right, pserv);
535 
536     default:
537         return g_strdup_printf("unknown");
538     }
539 }
540 
541 static void tcp_chr_connect(void *opaque)
542 {
543     Chardev *chr = CHARDEV(opaque);
544     SocketChardev *s = SOCKET_CHARDEV(opaque);
545 
546     g_free(chr->filename);
547     chr->filename = sockaddr_to_str(
548         &s->sioc->localAddr, s->sioc->localAddrLen,
549         &s->sioc->remoteAddr, s->sioc->remoteAddrLen,
550         s->is_listen, s->is_telnet);
551 
552     s->connected = 1;
553     chr->gsource = io_add_watch_poll(chr, s->ioc,
554                                        tcp_chr_read_poll,
555                                        tcp_chr_read,
556                                        chr, chr->gcontext);
557 
558     s->hup_source = qio_channel_create_watch(s->ioc, G_IO_HUP);
559     g_source_set_callback(s->hup_source, (GSourceFunc)tcp_chr_hup,
560                           chr, NULL);
561     g_source_attach(s->hup_source, chr->gcontext);
562 
563     qemu_chr_be_event(chr, CHR_EVENT_OPENED);
564 }
565 
566 static void tcp_chr_telnet_destroy(SocketChardev *s)
567 {
568     if (s->telnet_source) {
569         g_source_destroy(s->telnet_source);
570         g_source_unref(s->telnet_source);
571         s->telnet_source = NULL;
572     }
573 }
574 
575 static void tcp_chr_update_read_handler(Chardev *chr)
576 {
577     SocketChardev *s = SOCKET_CHARDEV(chr);
578 
579     if (s->listener) {
580         /*
581          * It's possible that chardev context is changed in
582          * qemu_chr_be_update_read_handlers().  Reset it for QIO net
583          * listener if there is.
584          */
585         qio_net_listener_set_client_func_full(s->listener, tcp_chr_accept,
586                                               chr, NULL, chr->gcontext);
587     }
588 
589     if (s->telnet_source) {
590         tcp_chr_telnet_init(CHARDEV(s));
591     }
592 
593     if (!s->connected) {
594         return;
595     }
596 
597     remove_fd_in_watch(chr);
598     if (s->ioc) {
599         chr->gsource = io_add_watch_poll(chr, s->ioc,
600                                            tcp_chr_read_poll,
601                                            tcp_chr_read, chr,
602                                            chr->gcontext);
603     }
604 }
605 
606 static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc,
607                                        GIOCondition cond G_GNUC_UNUSED,
608                                        gpointer user_data)
609 {
610     SocketChardev *s = user_data;
611     Chardev *chr = CHARDEV(s);
612     TCPChardevTelnetInit *init = s->telnet_init;
613     ssize_t ret;
614 
615     assert(init);
616 
617     ret = qio_channel_write(ioc, init->buf, init->buflen, NULL);
618     if (ret < 0) {
619         if (ret == QIO_CHANNEL_ERR_BLOCK) {
620             ret = 0;
621         } else {
622             tcp_chr_disconnect(chr);
623             goto end;
624         }
625     }
626     init->buflen -= ret;
627 
628     if (init->buflen == 0) {
629         tcp_chr_connect(chr);
630         goto end;
631     }
632 
633     memmove(init->buf, init->buf + ret, init->buflen);
634 
635     return G_SOURCE_CONTINUE;
636 
637 end:
638     g_free(s->telnet_init);
639     s->telnet_init = NULL;
640     g_source_unref(s->telnet_source);
641     s->telnet_source = NULL;
642     return G_SOURCE_REMOVE;
643 }
644 
645 static void tcp_chr_telnet_init(Chardev *chr)
646 {
647     SocketChardev *s = SOCKET_CHARDEV(chr);
648     TCPChardevTelnetInit *init;
649     size_t n = 0;
650 
651     /* Destroy existing task */
652     tcp_chr_telnet_destroy(s);
653 
654     if (s->telnet_init) {
655         /* We are possibly during a handshake already */
656         goto cont;
657     }
658 
659     s->telnet_init = g_new0(TCPChardevTelnetInit, 1);
660     init = s->telnet_init;
661 
662 #define IACSET(x, a, b, c)                      \
663     do {                                        \
664         x[n++] = a;                             \
665         x[n++] = b;                             \
666         x[n++] = c;                             \
667     } while (0)
668 
669     if (!s->is_tn3270) {
670         init->buflen = 12;
671         /* Prep the telnet negotion to put telnet in binary,
672          * no echo, single char mode */
673         IACSET(init->buf, 0xff, 0xfb, 0x01);  /* IAC WILL ECHO */
674         IACSET(init->buf, 0xff, 0xfb, 0x03);  /* IAC WILL Suppress go ahead */
675         IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL Binary */
676         IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO Binary */
677     } else {
678         init->buflen = 21;
679         /* Prep the TN3270 negotion based on RFC1576 */
680         IACSET(init->buf, 0xff, 0xfd, 0x19);  /* IAC DO EOR */
681         IACSET(init->buf, 0xff, 0xfb, 0x19);  /* IAC WILL EOR */
682         IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO BINARY */
683         IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL BINARY */
684         IACSET(init->buf, 0xff, 0xfd, 0x18);  /* IAC DO TERMINAL TYPE */
685         IACSET(init->buf, 0xff, 0xfa, 0x18);  /* IAC SB TERMINAL TYPE */
686         IACSET(init->buf, 0x01, 0xff, 0xf0);  /* SEND IAC SE */
687     }
688 
689 #undef IACSET
690 
691 cont:
692     s->telnet_source = qio_channel_add_watch_source(s->ioc, G_IO_OUT,
693                                                     tcp_chr_telnet_init_io,
694                                                     s, NULL,
695                                                     chr->gcontext);
696 }
697 
698 
699 static void tcp_chr_tls_handshake(QIOTask *task,
700                                   gpointer user_data)
701 {
702     Chardev *chr = user_data;
703     SocketChardev *s = user_data;
704 
705     if (qio_task_propagate_error(task, NULL)) {
706         tcp_chr_disconnect(chr);
707     } else {
708         if (s->do_telnetopt) {
709             tcp_chr_telnet_init(chr);
710         } else {
711             tcp_chr_connect(chr);
712         }
713     }
714 }
715 
716 
717 static void tcp_chr_tls_init(Chardev *chr)
718 {
719     SocketChardev *s = SOCKET_CHARDEV(chr);
720     QIOChannelTLS *tioc;
721     Error *err = NULL;
722     gchar *name;
723 
724     if (!machine_init_done) {
725         /* This will be postponed to machine_done notifier */
726         return;
727     }
728 
729     if (s->is_listen) {
730         tioc = qio_channel_tls_new_server(
731             s->ioc, s->tls_creds,
732             NULL, /* XXX Use an ACL */
733             &err);
734     } else {
735         tioc = qio_channel_tls_new_client(
736             s->ioc, s->tls_creds,
737             s->addr->u.inet.host,
738             &err);
739     }
740     if (tioc == NULL) {
741         error_free(err);
742         tcp_chr_disconnect(chr);
743         return;
744     }
745     name = g_strdup_printf("chardev-tls-%s-%s",
746                            s->is_listen ? "server" : "client",
747                            chr->label);
748     qio_channel_set_name(QIO_CHANNEL(tioc), name);
749     g_free(name);
750     object_unref(OBJECT(s->ioc));
751     s->ioc = QIO_CHANNEL(tioc);
752 
753     qio_channel_tls_handshake(tioc,
754                               tcp_chr_tls_handshake,
755                               chr,
756                               NULL,
757                               chr->gcontext);
758 }
759 
760 
761 static void tcp_chr_set_client_ioc_name(Chardev *chr,
762                                         QIOChannelSocket *sioc)
763 {
764     SocketChardev *s = SOCKET_CHARDEV(chr);
765     char *name;
766     name = g_strdup_printf("chardev-tcp-%s-%s",
767                            s->is_listen ? "server" : "client",
768                            chr->label);
769     qio_channel_set_name(QIO_CHANNEL(sioc), name);
770     g_free(name);
771 
772 }
773 
774 static int tcp_chr_new_client(Chardev *chr, QIOChannelSocket *sioc)
775 {
776     SocketChardev *s = SOCKET_CHARDEV(chr);
777 
778     if (s->ioc != NULL) {
779         return -1;
780     }
781 
782     s->ioc = QIO_CHANNEL(sioc);
783     object_ref(OBJECT(sioc));
784     s->sioc = sioc;
785     object_ref(OBJECT(sioc));
786 
787     qio_channel_set_blocking(s->ioc, false, NULL);
788 
789     if (s->do_nodelay) {
790         qio_channel_set_delay(s->ioc, false);
791     }
792     if (s->listener) {
793         qio_net_listener_set_client_func_full(s->listener, NULL, NULL,
794                                               NULL, chr->gcontext);
795     }
796 
797     if (s->tls_creds) {
798         tcp_chr_tls_init(chr);
799     } else {
800         if (s->do_telnetopt) {
801             tcp_chr_telnet_init(chr);
802         } else {
803             tcp_chr_connect(chr);
804         }
805     }
806 
807     return 0;
808 }
809 
810 
811 static int tcp_chr_add_client(Chardev *chr, int fd)
812 {
813     int ret;
814     QIOChannelSocket *sioc;
815 
816     sioc = qio_channel_socket_new_fd(fd, NULL);
817     if (!sioc) {
818         return -1;
819     }
820     tcp_chr_set_client_ioc_name(chr, sioc);
821     ret = tcp_chr_new_client(chr, sioc);
822     object_unref(OBJECT(sioc));
823     return ret;
824 }
825 
826 static void tcp_chr_accept(QIONetListener *listener,
827                            QIOChannelSocket *cioc,
828                            void *opaque)
829 {
830     Chardev *chr = CHARDEV(opaque);
831 
832     tcp_chr_set_client_ioc_name(chr, cioc);
833     tcp_chr_new_client(chr, cioc);
834 }
835 
836 static int tcp_chr_wait_connected(Chardev *chr, Error **errp)
837 {
838     SocketChardev *s = SOCKET_CHARDEV(chr);
839     QIOChannelSocket *sioc;
840 
841     /* It can't wait on s->connected, since it is set asynchronously
842      * in TLS and telnet cases, only wait for an accepted socket */
843     while (!s->ioc) {
844         if (s->is_listen) {
845             info_report("QEMU waiting for connection on: %s",
846                         chr->filename);
847             sioc = qio_net_listener_wait_client(s->listener);
848             tcp_chr_set_client_ioc_name(chr, sioc);
849             tcp_chr_new_client(chr, sioc);
850             object_unref(OBJECT(sioc));
851         } else {
852             sioc = qio_channel_socket_new();
853             tcp_chr_set_client_ioc_name(chr, sioc);
854             if (qio_channel_socket_connect_sync(sioc, s->addr, errp) < 0) {
855                 object_unref(OBJECT(sioc));
856                 return -1;
857             }
858             tcp_chr_new_client(chr, sioc);
859             object_unref(OBJECT(sioc));
860         }
861     }
862 
863     return 0;
864 }
865 
866 static void char_socket_finalize(Object *obj)
867 {
868     Chardev *chr = CHARDEV(obj);
869     SocketChardev *s = SOCKET_CHARDEV(obj);
870 
871     tcp_chr_free_connection(chr);
872     tcp_chr_reconn_timer_cancel(s);
873     qapi_free_SocketAddress(s->addr);
874     tcp_chr_telnet_destroy(s);
875     g_free(s->telnet_init);
876     if (s->listener) {
877         qio_net_listener_set_client_func_full(s->listener, NULL, NULL,
878                                               NULL, chr->gcontext);
879         object_unref(OBJECT(s->listener));
880     }
881     if (s->tls_creds) {
882         object_unref(OBJECT(s->tls_creds));
883     }
884 
885     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
886 }
887 
888 static void qemu_chr_socket_connected(QIOTask *task, void *opaque)
889 {
890     QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
891     Chardev *chr = CHARDEV(opaque);
892     SocketChardev *s = SOCKET_CHARDEV(chr);
893     Error *err = NULL;
894 
895     if (qio_task_propagate_error(task, &err)) {
896         check_report_connect_error(chr, err);
897         error_free(err);
898         goto cleanup;
899     }
900 
901     s->connect_err_reported = false;
902     tcp_chr_new_client(chr, sioc);
903 
904 cleanup:
905     object_unref(OBJECT(sioc));
906 }
907 
908 static void tcp_chr_connect_async(Chardev *chr)
909 {
910     SocketChardev *s = SOCKET_CHARDEV(chr);
911     QIOChannelSocket *sioc;
912 
913     sioc = qio_channel_socket_new();
914     tcp_chr_set_client_ioc_name(chr, sioc);
915     qio_channel_socket_connect_async(sioc, s->addr,
916                                      qemu_chr_socket_connected,
917                                      chr, NULL, chr->gcontext);
918 }
919 
920 static gboolean socket_reconnect_timeout(gpointer opaque)
921 {
922     Chardev *chr = CHARDEV(opaque);
923     SocketChardev *s = SOCKET_CHARDEV(opaque);
924 
925     g_source_unref(s->reconnect_timer);
926     s->reconnect_timer = NULL;
927 
928     if (chr->be_open) {
929         return false;
930     }
931 
932     tcp_chr_connect_async(chr);
933 
934     return false;
935 }
936 
937 static void qmp_chardev_open_socket(Chardev *chr,
938                                     ChardevBackend *backend,
939                                     bool *be_opened,
940                                     Error **errp)
941 {
942     SocketChardev *s = SOCKET_CHARDEV(chr);
943     ChardevSocket *sock = backend->u.socket.data;
944     bool do_nodelay     = sock->has_nodelay ? sock->nodelay : false;
945     bool is_listen      = sock->has_server  ? sock->server  : true;
946     bool is_telnet      = sock->has_telnet  ? sock->telnet  : false;
947     bool is_tn3270      = sock->has_tn3270  ? sock->tn3270  : false;
948     bool is_waitconnect = sock->has_wait    ? sock->wait    : false;
949     int64_t reconnect   = sock->has_reconnect ? sock->reconnect : 0;
950     QIOChannelSocket *sioc = NULL;
951     SocketAddress *addr;
952 
953     s->is_listen = is_listen;
954     s->is_telnet = is_telnet;
955     s->is_tn3270 = is_tn3270;
956     s->do_nodelay = do_nodelay;
957     if (sock->tls_creds) {
958         Object *creds;
959         creds = object_resolve_path_component(
960             object_get_objects_root(), sock->tls_creds);
961         if (!creds) {
962             error_setg(errp, "No TLS credentials with id '%s'",
963                        sock->tls_creds);
964             goto error;
965         }
966         s->tls_creds = (QCryptoTLSCreds *)
967             object_dynamic_cast(creds,
968                                 TYPE_QCRYPTO_TLS_CREDS);
969         if (!s->tls_creds) {
970             error_setg(errp, "Object with id '%s' is not TLS credentials",
971                        sock->tls_creds);
972             goto error;
973         }
974         object_ref(OBJECT(s->tls_creds));
975         if (is_listen) {
976             if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
977                 error_setg(errp, "%s",
978                            "Expected TLS credentials for server endpoint");
979                 goto error;
980             }
981         } else {
982             if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
983                 error_setg(errp, "%s",
984                            "Expected TLS credentials for client endpoint");
985                 goto error;
986             }
987         }
988     }
989 
990     s->addr = addr = socket_address_flatten(sock->addr);
991 
992     qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE);
993     /* TODO SOCKET_ADDRESS_FD where fd has AF_UNIX */
994     if (addr->type == SOCKET_ADDRESS_TYPE_UNIX) {
995         qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_FD_PASS);
996     }
997 
998     /* be isn't opened until we get a connection */
999     *be_opened = false;
1000 
1001     update_disconnected_filename(s);
1002 
1003     if (is_listen) {
1004         if (is_telnet || is_tn3270) {
1005             s->do_telnetopt = 1;
1006         }
1007     } else if (reconnect > 0) {
1008         s->reconnect_time = reconnect;
1009     }
1010 
1011     /* If reconnect_time is set, will do that in chr_machine_done. */
1012     if (!s->reconnect_time) {
1013         if (s->is_listen) {
1014             char *name;
1015             s->listener = qio_net_listener_new();
1016 
1017             name = g_strdup_printf("chardev-tcp-listener-%s", chr->label);
1018             qio_net_listener_set_name(s->listener, name);
1019             g_free(name);
1020 
1021             if (qio_net_listener_open_sync(s->listener, s->addr, errp) < 0) {
1022                 object_unref(OBJECT(s->listener));
1023                 s->listener = NULL;
1024                 goto error;
1025             }
1026 
1027             qapi_free_SocketAddress(s->addr);
1028             s->addr = socket_local_address(s->listener->sioc[0]->fd, errp);
1029             update_disconnected_filename(s);
1030 
1031             if (is_waitconnect &&
1032                 qemu_chr_wait_connected(chr, errp) < 0) {
1033                 return;
1034             }
1035             if (!s->ioc) {
1036                 qio_net_listener_set_client_func_full(s->listener,
1037                                                       tcp_chr_accept,
1038                                                       chr, NULL,
1039                                                       chr->gcontext);
1040             }
1041         } else if (qemu_chr_wait_connected(chr, errp) < 0) {
1042             goto error;
1043         }
1044     }
1045 
1046     return;
1047 
1048 error:
1049     if (sioc) {
1050         object_unref(OBJECT(sioc));
1051     }
1052 }
1053 
1054 static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
1055                                   Error **errp)
1056 {
1057     bool is_listen      = qemu_opt_get_bool(opts, "server", false);
1058     bool is_waitconnect = is_listen && qemu_opt_get_bool(opts, "wait", true);
1059     bool is_telnet      = qemu_opt_get_bool(opts, "telnet", false);
1060     bool is_tn3270      = qemu_opt_get_bool(opts, "tn3270", false);
1061     bool do_nodelay     = !qemu_opt_get_bool(opts, "delay", true);
1062     int64_t reconnect   = qemu_opt_get_number(opts, "reconnect", 0);
1063     const char *path = qemu_opt_get(opts, "path");
1064     const char *host = qemu_opt_get(opts, "host");
1065     const char *port = qemu_opt_get(opts, "port");
1066     const char *fd = qemu_opt_get(opts, "fd");
1067     const char *tls_creds = qemu_opt_get(opts, "tls-creds");
1068     SocketAddressLegacy *addr;
1069     ChardevSocket *sock;
1070 
1071     if ((!!path + !!fd + !!host) != 1) {
1072         error_setg(errp,
1073                    "Exactly one of 'path', 'fd' or 'host' required");
1074         return;
1075     }
1076 
1077     backend->type = CHARDEV_BACKEND_KIND_SOCKET;
1078     if (path) {
1079         if (tls_creds) {
1080             error_setg(errp, "TLS can only be used over TCP socket");
1081             return;
1082         }
1083     } else if (host) {
1084         if (!port) {
1085             error_setg(errp, "chardev: socket: no port given");
1086             return;
1087         }
1088     } else if (fd) {
1089         /* We don't know what host to validate against when in client mode */
1090         if (tls_creds && !is_listen) {
1091             error_setg(errp, "TLS can not be used with pre-opened client FD");
1092             return;
1093         }
1094     } else {
1095         g_assert_not_reached();
1096     }
1097 
1098     sock = backend->u.socket.data = g_new0(ChardevSocket, 1);
1099     qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock));
1100 
1101     sock->has_nodelay = true;
1102     sock->nodelay = do_nodelay;
1103     sock->has_server = true;
1104     sock->server = is_listen;
1105     sock->has_telnet = true;
1106     sock->telnet = is_telnet;
1107     sock->has_tn3270 = true;
1108     sock->tn3270 = is_tn3270;
1109     sock->has_wait = true;
1110     sock->wait = is_waitconnect;
1111     sock->has_reconnect = true;
1112     sock->reconnect = reconnect;
1113     sock->tls_creds = g_strdup(tls_creds);
1114 
1115     addr = g_new0(SocketAddressLegacy, 1);
1116     if (path) {
1117         UnixSocketAddress *q_unix;
1118         addr->type = SOCKET_ADDRESS_LEGACY_KIND_UNIX;
1119         q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
1120         q_unix->path = g_strdup(path);
1121     } else if (host) {
1122         addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;
1123         addr->u.inet.data = g_new(InetSocketAddress, 1);
1124         *addr->u.inet.data = (InetSocketAddress) {
1125             .host = g_strdup(host),
1126             .port = g_strdup(port),
1127             .has_to = qemu_opt_get(opts, "to"),
1128             .to = qemu_opt_get_number(opts, "to", 0),
1129             .has_ipv4 = qemu_opt_get(opts, "ipv4"),
1130             .ipv4 = qemu_opt_get_bool(opts, "ipv4", 0),
1131             .has_ipv6 = qemu_opt_get(opts, "ipv6"),
1132             .ipv6 = qemu_opt_get_bool(opts, "ipv6", 0),
1133         };
1134     } else if (fd) {
1135         addr->type = SOCKET_ADDRESS_LEGACY_KIND_FD;
1136         addr->u.fd.data = g_new(String, 1);
1137         addr->u.fd.data->str = g_strdup(fd);
1138     } else {
1139         g_assert_not_reached();
1140     }
1141     sock->addr = addr;
1142 }
1143 
1144 static void
1145 char_socket_get_addr(Object *obj, Visitor *v, const char *name,
1146                      void *opaque, Error **errp)
1147 {
1148     SocketChardev *s = SOCKET_CHARDEV(obj);
1149 
1150     visit_type_SocketAddress(v, name, &s->addr, errp);
1151 }
1152 
1153 static bool
1154 char_socket_get_connected(Object *obj, Error **errp)
1155 {
1156     SocketChardev *s = SOCKET_CHARDEV(obj);
1157 
1158     return s->connected;
1159 }
1160 
1161 static int tcp_chr_machine_done_hook(Chardev *chr)
1162 {
1163     SocketChardev *s = SOCKET_CHARDEV(chr);
1164 
1165     if (s->reconnect_time) {
1166         tcp_chr_connect_async(chr);
1167     }
1168 
1169     if (s->ioc && s->tls_creds) {
1170         tcp_chr_tls_init(chr);
1171     }
1172 
1173     return 0;
1174 }
1175 
1176 static void char_socket_class_init(ObjectClass *oc, void *data)
1177 {
1178     ChardevClass *cc = CHARDEV_CLASS(oc);
1179 
1180     cc->parse = qemu_chr_parse_socket;
1181     cc->open = qmp_chardev_open_socket;
1182     cc->chr_wait_connected = tcp_chr_wait_connected;
1183     cc->chr_write = tcp_chr_write;
1184     cc->chr_sync_read = tcp_chr_sync_read;
1185     cc->chr_disconnect = tcp_chr_disconnect;
1186     cc->get_msgfds = tcp_get_msgfds;
1187     cc->set_msgfds = tcp_set_msgfds;
1188     cc->chr_add_client = tcp_chr_add_client;
1189     cc->chr_add_watch = tcp_chr_add_watch;
1190     cc->chr_update_read_handler = tcp_chr_update_read_handler;
1191     cc->chr_machine_done = tcp_chr_machine_done_hook;
1192 
1193     object_class_property_add(oc, "addr", "SocketAddress",
1194                               char_socket_get_addr, NULL,
1195                               NULL, NULL, &error_abort);
1196 
1197     object_class_property_add_bool(oc, "connected", char_socket_get_connected,
1198                                    NULL, &error_abort);
1199 }
1200 
1201 static const TypeInfo char_socket_type_info = {
1202     .name = TYPE_CHARDEV_SOCKET,
1203     .parent = TYPE_CHARDEV,
1204     .instance_size = sizeof(SocketChardev),
1205     .instance_finalize = char_socket_finalize,
1206     .class_init = char_socket_class_init,
1207 };
1208 
1209 static void register_types(void)
1210 {
1211     type_register_static(&char_socket_type_info);
1212 }
1213 
1214 type_init(register_types);
1215