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