xref: /openbmc/qemu/chardev/char-socket.c (revision d1fd31f8)
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, no matter what */
138         if (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     if (s->ioc) {
554         chr->gsource = io_add_watch_poll(chr, s->ioc,
555                                            tcp_chr_read_poll,
556                                            tcp_chr_read,
557                                            chr, chr->gcontext);
558     }
559 
560     s->hup_source = qio_channel_create_watch(s->ioc, G_IO_HUP);
561     g_source_set_callback(s->hup_source, (GSourceFunc)tcp_chr_hup,
562                           chr, NULL);
563     g_source_attach(s->hup_source, chr->gcontext);
564 
565     qemu_chr_be_event(chr, CHR_EVENT_OPENED);
566 }
567 
568 static void tcp_chr_telnet_destroy(SocketChardev *s)
569 {
570     if (s->telnet_source) {
571         g_source_destroy(s->telnet_source);
572         g_source_unref(s->telnet_source);
573         s->telnet_source = NULL;
574     }
575 }
576 
577 static void tcp_chr_update_read_handler(Chardev *chr)
578 {
579     SocketChardev *s = SOCKET_CHARDEV(chr);
580 
581     if (s->listener) {
582         /*
583          * It's possible that chardev context is changed in
584          * qemu_chr_be_update_read_handlers().  Reset it for QIO net
585          * listener if there is.
586          */
587         qio_net_listener_set_client_func_full(s->listener, tcp_chr_accept,
588                                               chr, NULL, chr->gcontext);
589     }
590 
591     if (s->telnet_source) {
592         tcp_chr_telnet_init(CHARDEV(s));
593     }
594 
595     if (!s->connected) {
596         return;
597     }
598 
599     remove_fd_in_watch(chr);
600     if (s->ioc) {
601         chr->gsource = io_add_watch_poll(chr, s->ioc,
602                                            tcp_chr_read_poll,
603                                            tcp_chr_read, chr,
604                                            chr->gcontext);
605     }
606 }
607 
608 static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc,
609                                        GIOCondition cond G_GNUC_UNUSED,
610                                        gpointer user_data)
611 {
612     SocketChardev *s = user_data;
613     Chardev *chr = CHARDEV(s);
614     TCPChardevTelnetInit *init = s->telnet_init;
615     ssize_t ret;
616 
617     assert(init);
618 
619     ret = qio_channel_write(ioc, init->buf, init->buflen, NULL);
620     if (ret < 0) {
621         if (ret == QIO_CHANNEL_ERR_BLOCK) {
622             ret = 0;
623         } else {
624             tcp_chr_disconnect(chr);
625             goto end;
626         }
627     }
628     init->buflen -= ret;
629 
630     if (init->buflen == 0) {
631         tcp_chr_connect(chr);
632         goto end;
633     }
634 
635     memmove(init->buf, init->buf + ret, init->buflen);
636 
637     return G_SOURCE_CONTINUE;
638 
639 end:
640     g_free(s->telnet_init);
641     s->telnet_init = NULL;
642     g_source_unref(s->telnet_source);
643     s->telnet_source = NULL;
644     return G_SOURCE_REMOVE;
645 }
646 
647 static void tcp_chr_telnet_init(Chardev *chr)
648 {
649     SocketChardev *s = SOCKET_CHARDEV(chr);
650     TCPChardevTelnetInit *init;
651     size_t n = 0;
652 
653     /* Destroy existing task */
654     tcp_chr_telnet_destroy(s);
655 
656     if (s->telnet_init) {
657         /* We are possibly during a handshake already */
658         goto cont;
659     }
660 
661     s->telnet_init = g_new0(TCPChardevTelnetInit, 1);
662     init = s->telnet_init;
663 
664 #define IACSET(x, a, b, c)                      \
665     do {                                        \
666         x[n++] = a;                             \
667         x[n++] = b;                             \
668         x[n++] = c;                             \
669     } while (0)
670 
671     if (!s->is_tn3270) {
672         init->buflen = 12;
673         /* Prep the telnet negotion to put telnet in binary,
674          * no echo, single char mode */
675         IACSET(init->buf, 0xff, 0xfb, 0x01);  /* IAC WILL ECHO */
676         IACSET(init->buf, 0xff, 0xfb, 0x03);  /* IAC WILL Suppress go ahead */
677         IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL Binary */
678         IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO Binary */
679     } else {
680         init->buflen = 21;
681         /* Prep the TN3270 negotion based on RFC1576 */
682         IACSET(init->buf, 0xff, 0xfd, 0x19);  /* IAC DO EOR */
683         IACSET(init->buf, 0xff, 0xfb, 0x19);  /* IAC WILL EOR */
684         IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO BINARY */
685         IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL BINARY */
686         IACSET(init->buf, 0xff, 0xfd, 0x18);  /* IAC DO TERMINAL TYPE */
687         IACSET(init->buf, 0xff, 0xfa, 0x18);  /* IAC SB TERMINAL TYPE */
688         IACSET(init->buf, 0x01, 0xff, 0xf0);  /* SEND IAC SE */
689     }
690 
691 #undef IACSET
692 
693 cont:
694     s->telnet_source = qio_channel_add_watch_source(s->ioc, G_IO_OUT,
695                                                     tcp_chr_telnet_init_io,
696                                                     s, NULL,
697                                                     chr->gcontext);
698 }
699 
700 
701 static void tcp_chr_tls_handshake(QIOTask *task,
702                                   gpointer user_data)
703 {
704     Chardev *chr = user_data;
705     SocketChardev *s = user_data;
706 
707     if (qio_task_propagate_error(task, NULL)) {
708         tcp_chr_disconnect(chr);
709     } else {
710         if (s->do_telnetopt) {
711             tcp_chr_telnet_init(chr);
712         } else {
713             tcp_chr_connect(chr);
714         }
715     }
716 }
717 
718 
719 static void tcp_chr_tls_init(Chardev *chr)
720 {
721     SocketChardev *s = SOCKET_CHARDEV(chr);
722     QIOChannelTLS *tioc;
723     Error *err = NULL;
724     gchar *name;
725 
726     if (!machine_init_done) {
727         /* This will be postponed to machine_done notifier */
728         return;
729     }
730 
731     if (s->is_listen) {
732         tioc = qio_channel_tls_new_server(
733             s->ioc, s->tls_creds,
734             NULL, /* XXX Use an ACL */
735             &err);
736     } else {
737         tioc = qio_channel_tls_new_client(
738             s->ioc, s->tls_creds,
739             s->addr->u.inet.host,
740             &err);
741     }
742     if (tioc == NULL) {
743         error_free(err);
744         tcp_chr_disconnect(chr);
745         return;
746     }
747     name = g_strdup_printf("chardev-tls-%s-%s",
748                            s->is_listen ? "server" : "client",
749                            chr->label);
750     qio_channel_set_name(QIO_CHANNEL(tioc), name);
751     g_free(name);
752     object_unref(OBJECT(s->ioc));
753     s->ioc = QIO_CHANNEL(tioc);
754 
755     qio_channel_tls_handshake(tioc,
756                               tcp_chr_tls_handshake,
757                               chr,
758                               NULL,
759                               chr->gcontext);
760 }
761 
762 
763 static void tcp_chr_set_client_ioc_name(Chardev *chr,
764                                         QIOChannelSocket *sioc)
765 {
766     SocketChardev *s = SOCKET_CHARDEV(chr);
767     char *name;
768     name = g_strdup_printf("chardev-tcp-%s-%s",
769                            s->is_listen ? "server" : "client",
770                            chr->label);
771     qio_channel_set_name(QIO_CHANNEL(sioc), name);
772     g_free(name);
773 
774 }
775 
776 static int tcp_chr_new_client(Chardev *chr, QIOChannelSocket *sioc)
777 {
778     SocketChardev *s = SOCKET_CHARDEV(chr);
779 
780     if (s->ioc != NULL) {
781         return -1;
782     }
783 
784     s->ioc = QIO_CHANNEL(sioc);
785     object_ref(OBJECT(sioc));
786     s->sioc = sioc;
787     object_ref(OBJECT(sioc));
788 
789     qio_channel_set_blocking(s->ioc, false, NULL);
790 
791     if (s->do_nodelay) {
792         qio_channel_set_delay(s->ioc, false);
793     }
794     if (s->listener) {
795         qio_net_listener_set_client_func_full(s->listener, NULL, NULL,
796                                               NULL, chr->gcontext);
797     }
798 
799     if (s->tls_creds) {
800         tcp_chr_tls_init(chr);
801     } else {
802         if (s->do_telnetopt) {
803             tcp_chr_telnet_init(chr);
804         } else {
805             tcp_chr_connect(chr);
806         }
807     }
808 
809     return 0;
810 }
811 
812 
813 static int tcp_chr_add_client(Chardev *chr, int fd)
814 {
815     int ret;
816     QIOChannelSocket *sioc;
817 
818     sioc = qio_channel_socket_new_fd(fd, NULL);
819     if (!sioc) {
820         return -1;
821     }
822     tcp_chr_set_client_ioc_name(chr, sioc);
823     ret = tcp_chr_new_client(chr, sioc);
824     object_unref(OBJECT(sioc));
825     return ret;
826 }
827 
828 static void tcp_chr_accept(QIONetListener *listener,
829                            QIOChannelSocket *cioc,
830                            void *opaque)
831 {
832     Chardev *chr = CHARDEV(opaque);
833 
834     tcp_chr_set_client_ioc_name(chr, cioc);
835     tcp_chr_new_client(chr, cioc);
836 }
837 
838 static int tcp_chr_wait_connected(Chardev *chr, Error **errp)
839 {
840     SocketChardev *s = SOCKET_CHARDEV(chr);
841     QIOChannelSocket *sioc;
842 
843     /* It can't wait on s->connected, since it is set asynchronously
844      * in TLS and telnet cases, only wait for an accepted socket */
845     while (!s->ioc) {
846         if (s->is_listen) {
847             info_report("QEMU waiting for connection on: %s",
848                         chr->filename);
849             sioc = qio_net_listener_wait_client(s->listener);
850             tcp_chr_set_client_ioc_name(chr, sioc);
851             tcp_chr_new_client(chr, sioc);
852             object_unref(OBJECT(sioc));
853         } else {
854             sioc = qio_channel_socket_new();
855             tcp_chr_set_client_ioc_name(chr, sioc);
856             if (qio_channel_socket_connect_sync(sioc, s->addr, errp) < 0) {
857                 object_unref(OBJECT(sioc));
858                 return -1;
859             }
860             tcp_chr_new_client(chr, sioc);
861             object_unref(OBJECT(sioc));
862         }
863     }
864 
865     return 0;
866 }
867 
868 static void char_socket_finalize(Object *obj)
869 {
870     Chardev *chr = CHARDEV(obj);
871     SocketChardev *s = SOCKET_CHARDEV(obj);
872 
873     tcp_chr_free_connection(chr);
874     tcp_chr_reconn_timer_cancel(s);
875     qapi_free_SocketAddress(s->addr);
876     tcp_chr_telnet_destroy(s);
877     g_free(s->telnet_init);
878     if (s->listener) {
879         qio_net_listener_set_client_func_full(s->listener, NULL, NULL,
880                                               NULL, chr->gcontext);
881         object_unref(OBJECT(s->listener));
882     }
883     if (s->tls_creds) {
884         object_unref(OBJECT(s->tls_creds));
885     }
886 
887     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
888 }
889 
890 static void qemu_chr_socket_connected(QIOTask *task, void *opaque)
891 {
892     QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
893     Chardev *chr = CHARDEV(opaque);
894     SocketChardev *s = SOCKET_CHARDEV(chr);
895     Error *err = NULL;
896 
897     if (qio_task_propagate_error(task, &err)) {
898         check_report_connect_error(chr, err);
899         error_free(err);
900         goto cleanup;
901     }
902 
903     s->connect_err_reported = false;
904     tcp_chr_new_client(chr, sioc);
905 
906 cleanup:
907     object_unref(OBJECT(sioc));
908 }
909 
910 static void tcp_chr_connect_async(Chardev *chr)
911 {
912     SocketChardev *s = SOCKET_CHARDEV(chr);
913     QIOChannelSocket *sioc;
914 
915     sioc = qio_channel_socket_new();
916     tcp_chr_set_client_ioc_name(chr, sioc);
917     qio_channel_socket_connect_async(sioc, s->addr,
918                                      qemu_chr_socket_connected,
919                                      chr, NULL, chr->gcontext);
920 }
921 
922 static gboolean socket_reconnect_timeout(gpointer opaque)
923 {
924     Chardev *chr = CHARDEV(opaque);
925     SocketChardev *s = SOCKET_CHARDEV(opaque);
926 
927     g_source_unref(s->reconnect_timer);
928     s->reconnect_timer = NULL;
929 
930     if (chr->be_open) {
931         return false;
932     }
933 
934     tcp_chr_connect_async(chr);
935 
936     return false;
937 }
938 
939 static void qmp_chardev_open_socket(Chardev *chr,
940                                     ChardevBackend *backend,
941                                     bool *be_opened,
942                                     Error **errp)
943 {
944     SocketChardev *s = SOCKET_CHARDEV(chr);
945     ChardevSocket *sock = backend->u.socket.data;
946     bool do_nodelay     = sock->has_nodelay ? sock->nodelay : false;
947     bool is_listen      = sock->has_server  ? sock->server  : true;
948     bool is_telnet      = sock->has_telnet  ? sock->telnet  : false;
949     bool is_tn3270      = sock->has_tn3270  ? sock->tn3270  : false;
950     bool is_waitconnect = sock->has_wait    ? sock->wait    : false;
951     int64_t reconnect   = sock->has_reconnect ? sock->reconnect : 0;
952     QIOChannelSocket *sioc = NULL;
953     SocketAddress *addr;
954 
955     s->is_listen = is_listen;
956     s->is_telnet = is_telnet;
957     s->is_tn3270 = is_tn3270;
958     s->do_nodelay = do_nodelay;
959     if (sock->tls_creds) {
960         Object *creds;
961         creds = object_resolve_path_component(
962             object_get_objects_root(), sock->tls_creds);
963         if (!creds) {
964             error_setg(errp, "No TLS credentials with id '%s'",
965                        sock->tls_creds);
966             goto error;
967         }
968         s->tls_creds = (QCryptoTLSCreds *)
969             object_dynamic_cast(creds,
970                                 TYPE_QCRYPTO_TLS_CREDS);
971         if (!s->tls_creds) {
972             error_setg(errp, "Object with id '%s' is not TLS credentials",
973                        sock->tls_creds);
974             goto error;
975         }
976         object_ref(OBJECT(s->tls_creds));
977         if (is_listen) {
978             if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
979                 error_setg(errp, "%s",
980                            "Expected TLS credentials for server endpoint");
981                 goto error;
982             }
983         } else {
984             if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
985                 error_setg(errp, "%s",
986                            "Expected TLS credentials for client endpoint");
987                 goto error;
988             }
989         }
990     }
991 
992     s->addr = addr = socket_address_flatten(sock->addr);
993 
994     qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE);
995     /* TODO SOCKET_ADDRESS_FD where fd has AF_UNIX */
996     if (addr->type == SOCKET_ADDRESS_TYPE_UNIX) {
997         qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_FD_PASS);
998     }
999 
1000     /* be isn't opened until we get a connection */
1001     *be_opened = false;
1002 
1003     update_disconnected_filename(s);
1004 
1005     if (is_listen) {
1006         if (is_telnet || is_tn3270) {
1007             s->do_telnetopt = 1;
1008         }
1009     } else if (reconnect > 0) {
1010         s->reconnect_time = reconnect;
1011     }
1012 
1013     /* If reconnect_time is set, will do that in chr_machine_done. */
1014     if (!s->reconnect_time) {
1015         if (s->is_listen) {
1016             char *name;
1017             s->listener = qio_net_listener_new();
1018 
1019             name = g_strdup_printf("chardev-tcp-listener-%s", chr->label);
1020             qio_net_listener_set_name(s->listener, name);
1021             g_free(name);
1022 
1023             if (qio_net_listener_open_sync(s->listener, s->addr, errp) < 0) {
1024                 object_unref(OBJECT(s->listener));
1025                 s->listener = NULL;
1026                 goto error;
1027             }
1028 
1029             qapi_free_SocketAddress(s->addr);
1030             s->addr = socket_local_address(s->listener->sioc[0]->fd, errp);
1031             update_disconnected_filename(s);
1032 
1033             if (is_waitconnect &&
1034                 qemu_chr_wait_connected(chr, errp) < 0) {
1035                 return;
1036             }
1037             if (!s->ioc) {
1038                 qio_net_listener_set_client_func_full(s->listener,
1039                                                       tcp_chr_accept,
1040                                                       chr, NULL,
1041                                                       chr->gcontext);
1042             }
1043         } else if (qemu_chr_wait_connected(chr, errp) < 0) {
1044             goto error;
1045         }
1046     }
1047 
1048     return;
1049 
1050 error:
1051     if (sioc) {
1052         object_unref(OBJECT(sioc));
1053     }
1054 }
1055 
1056 static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
1057                                   Error **errp)
1058 {
1059     bool is_listen      = qemu_opt_get_bool(opts, "server", false);
1060     bool is_waitconnect = is_listen && qemu_opt_get_bool(opts, "wait", true);
1061     bool is_telnet      = qemu_opt_get_bool(opts, "telnet", false);
1062     bool is_tn3270      = qemu_opt_get_bool(opts, "tn3270", false);
1063     bool do_nodelay     = !qemu_opt_get_bool(opts, "delay", true);
1064     int64_t reconnect   = qemu_opt_get_number(opts, "reconnect", 0);
1065     const char *path = qemu_opt_get(opts, "path");
1066     const char *host = qemu_opt_get(opts, "host");
1067     const char *port = qemu_opt_get(opts, "port");
1068     const char *fd = qemu_opt_get(opts, "fd");
1069     const char *tls_creds = qemu_opt_get(opts, "tls-creds");
1070     SocketAddressLegacy *addr;
1071     ChardevSocket *sock;
1072 
1073     if ((!!path + !!fd + !!host) != 1) {
1074         error_setg(errp,
1075                    "Exactly one of 'path', 'fd' or 'host' required");
1076         return;
1077     }
1078 
1079     backend->type = CHARDEV_BACKEND_KIND_SOCKET;
1080     if (path) {
1081         if (tls_creds) {
1082             error_setg(errp, "TLS can only be used over TCP socket");
1083             return;
1084         }
1085     } else if (host) {
1086         if (!port) {
1087             error_setg(errp, "chardev: socket: no port given");
1088             return;
1089         }
1090     } else if (fd) {
1091         /* We don't know what host to validate against when in client mode */
1092         if (tls_creds && !is_listen) {
1093             error_setg(errp, "TLS can not be used with pre-opened client FD");
1094             return;
1095         }
1096     } else {
1097         g_assert_not_reached();
1098     }
1099 
1100     sock = backend->u.socket.data = g_new0(ChardevSocket, 1);
1101     qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock));
1102 
1103     sock->has_nodelay = true;
1104     sock->nodelay = do_nodelay;
1105     sock->has_server = true;
1106     sock->server = is_listen;
1107     sock->has_telnet = true;
1108     sock->telnet = is_telnet;
1109     sock->has_tn3270 = true;
1110     sock->tn3270 = is_tn3270;
1111     sock->has_wait = true;
1112     sock->wait = is_waitconnect;
1113     sock->has_reconnect = true;
1114     sock->reconnect = reconnect;
1115     sock->tls_creds = g_strdup(tls_creds);
1116 
1117     addr = g_new0(SocketAddressLegacy, 1);
1118     if (path) {
1119         UnixSocketAddress *q_unix;
1120         addr->type = SOCKET_ADDRESS_LEGACY_KIND_UNIX;
1121         q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
1122         q_unix->path = g_strdup(path);
1123     } else if (host) {
1124         addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;
1125         addr->u.inet.data = g_new(InetSocketAddress, 1);
1126         *addr->u.inet.data = (InetSocketAddress) {
1127             .host = g_strdup(host),
1128             .port = g_strdup(port),
1129             .has_to = qemu_opt_get(opts, "to"),
1130             .to = qemu_opt_get_number(opts, "to", 0),
1131             .has_ipv4 = qemu_opt_get(opts, "ipv4"),
1132             .ipv4 = qemu_opt_get_bool(opts, "ipv4", 0),
1133             .has_ipv6 = qemu_opt_get(opts, "ipv6"),
1134             .ipv6 = qemu_opt_get_bool(opts, "ipv6", 0),
1135         };
1136     } else if (fd) {
1137         addr->type = SOCKET_ADDRESS_LEGACY_KIND_FD;
1138         addr->u.fd.data = g_new(String, 1);
1139         addr->u.fd.data->str = g_strdup(fd);
1140     } else {
1141         g_assert_not_reached();
1142     }
1143     sock->addr = addr;
1144 }
1145 
1146 static void
1147 char_socket_get_addr(Object *obj, Visitor *v, const char *name,
1148                      void *opaque, Error **errp)
1149 {
1150     SocketChardev *s = SOCKET_CHARDEV(obj);
1151 
1152     visit_type_SocketAddress(v, name, &s->addr, errp);
1153 }
1154 
1155 static bool
1156 char_socket_get_connected(Object *obj, Error **errp)
1157 {
1158     SocketChardev *s = SOCKET_CHARDEV(obj);
1159 
1160     return s->connected;
1161 }
1162 
1163 static int tcp_chr_machine_done_hook(Chardev *chr)
1164 {
1165     SocketChardev *s = SOCKET_CHARDEV(chr);
1166 
1167     if (s->reconnect_time) {
1168         tcp_chr_connect_async(chr);
1169     }
1170 
1171     if (s->ioc && s->tls_creds) {
1172         tcp_chr_tls_init(chr);
1173     }
1174 
1175     return 0;
1176 }
1177 
1178 static void char_socket_class_init(ObjectClass *oc, void *data)
1179 {
1180     ChardevClass *cc = CHARDEV_CLASS(oc);
1181 
1182     cc->parse = qemu_chr_parse_socket;
1183     cc->open = qmp_chardev_open_socket;
1184     cc->chr_wait_connected = tcp_chr_wait_connected;
1185     cc->chr_write = tcp_chr_write;
1186     cc->chr_sync_read = tcp_chr_sync_read;
1187     cc->chr_disconnect = tcp_chr_disconnect;
1188     cc->get_msgfds = tcp_get_msgfds;
1189     cc->set_msgfds = tcp_set_msgfds;
1190     cc->chr_add_client = tcp_chr_add_client;
1191     cc->chr_add_watch = tcp_chr_add_watch;
1192     cc->chr_update_read_handler = tcp_chr_update_read_handler;
1193     cc->chr_machine_done = tcp_chr_machine_done_hook;
1194 
1195     object_class_property_add(oc, "addr", "SocketAddress",
1196                               char_socket_get_addr, NULL,
1197                               NULL, NULL, &error_abort);
1198 
1199     object_class_property_add_bool(oc, "connected", char_socket_get_connected,
1200                                    NULL, &error_abort);
1201 }
1202 
1203 static const TypeInfo char_socket_type_info = {
1204     .name = TYPE_CHARDEV_SOCKET,
1205     .parent = TYPE_CHARDEV,
1206     .instance_size = sizeof(SocketChardev),
1207     .instance_finalize = char_socket_finalize,
1208     .class_init = char_socket_class_init,
1209 };
1210 
1211 static void register_types(void)
1212 {
1213     type_register_static(&char_socket_type_info);
1214 }
1215 
1216 type_init(register_types);
1217