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