Commit ffd843bcdc46768f26507f0889c92f4bda287986
1 parent
1cb6c3fd
Run monitor over unix domain sockets, by Anthony Liguori.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2259 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
102 additions
and
19 deletions
qemu-doc.texi
@@ -586,6 +586,11 @@ MAGIC_SYSRQ sequence if you use a telnet that supports sending the break | @@ -586,6 +586,11 @@ MAGIC_SYSRQ sequence if you use a telnet that supports sending the break | ||
586 | sequence. Typically in unix telnet you do it with Control-] and then | 586 | sequence. Typically in unix telnet you do it with Control-] and then |
587 | type "send break" followed by pressing the enter key. | 587 | type "send break" followed by pressing the enter key. |
588 | 588 | ||
589 | +@item unix:path[,server][,nowait] | ||
590 | +A unix domain socket is used instead of a tcp socket. The option works the | ||
591 | +same as if you had specified @code{-serial tcp} except the unix domain socket | ||
592 | +@var{path} is used for connections. | ||
593 | + | ||
589 | @end table | 594 | @end table |
590 | 595 | ||
591 | @item -parallel dev | 596 | @item -parallel dev |
qemu_socket.h
@@ -19,6 +19,7 @@ | @@ -19,6 +19,7 @@ | ||
19 | #include <sys/socket.h> | 19 | #include <sys/socket.h> |
20 | #include <netinet/in.h> | 20 | #include <netinet/in.h> |
21 | #include <netinet/tcp.h> | 21 | #include <netinet/tcp.h> |
22 | +#include <sys/un.h> | ||
22 | 23 | ||
23 | #define socket_error() errno | 24 | #define socket_error() errno |
24 | #define closesocket(s) close(s) | 25 | #define closesocket(s) close(s) |
vl.c
@@ -2206,6 +2206,7 @@ static void udp_chr_add_read_handler(CharDriverState *chr, | @@ -2206,6 +2206,7 @@ static void udp_chr_add_read_handler(CharDriverState *chr, | ||
2206 | } | 2206 | } |
2207 | 2207 | ||
2208 | int parse_host_port(struct sockaddr_in *saddr, const char *str); | 2208 | int parse_host_port(struct sockaddr_in *saddr, const char *str); |
2209 | +int parse_unix_path(struct sockaddr_un *uaddr, const char *str); | ||
2209 | int parse_host_src_port(struct sockaddr_in *haddr, | 2210 | int parse_host_src_port(struct sockaddr_in *haddr, |
2210 | struct sockaddr_in *saddr, | 2211 | struct sockaddr_in *saddr, |
2211 | const char *str); | 2212 | const char *str); |
@@ -2270,6 +2271,7 @@ typedef struct { | @@ -2270,6 +2271,7 @@ typedef struct { | ||
2270 | int connected; | 2271 | int connected; |
2271 | int max_size; | 2272 | int max_size; |
2272 | int do_telnetopt; | 2273 | int do_telnetopt; |
2274 | + int is_unix; | ||
2273 | } TCPCharDriver; | 2275 | } TCPCharDriver; |
2274 | 2276 | ||
2275 | static void tcp_chr_accept(void *opaque); | 2277 | static void tcp_chr_accept(void *opaque); |
@@ -2291,6 +2293,8 @@ static int tcp_chr_read_poll(void *opaque) | @@ -2291,6 +2293,8 @@ static int tcp_chr_read_poll(void *opaque) | ||
2291 | TCPCharDriver *s = chr->opaque; | 2293 | TCPCharDriver *s = chr->opaque; |
2292 | if (!s->connected) | 2294 | if (!s->connected) |
2293 | return 0; | 2295 | return 0; |
2296 | + if (!s->fd_can_read) | ||
2297 | + return 0; | ||
2294 | s->max_size = s->fd_can_read(s->fd_opaque); | 2298 | s->max_size = s->fd_can_read(s->fd_opaque); |
2295 | return s->max_size; | 2299 | return s->max_size; |
2296 | } | 2300 | } |
@@ -2416,12 +2420,25 @@ static void tcp_chr_accept(void *opaque) | @@ -2416,12 +2420,25 @@ static void tcp_chr_accept(void *opaque) | ||
2416 | CharDriverState *chr = opaque; | 2420 | CharDriverState *chr = opaque; |
2417 | TCPCharDriver *s = chr->opaque; | 2421 | TCPCharDriver *s = chr->opaque; |
2418 | struct sockaddr_in saddr; | 2422 | struct sockaddr_in saddr; |
2423 | +#ifndef _WIN32 | ||
2424 | + struct sockaddr_un uaddr; | ||
2425 | +#endif | ||
2426 | + struct sockaddr *addr; | ||
2419 | socklen_t len; | 2427 | socklen_t len; |
2420 | int fd; | 2428 | int fd; |
2421 | 2429 | ||
2422 | for(;;) { | 2430 | for(;;) { |
2423 | - len = sizeof(saddr); | ||
2424 | - fd = accept(s->listen_fd, (struct sockaddr *)&saddr, &len); | 2431 | +#ifndef _WIN32 |
2432 | + if (s->is_unix) { | ||
2433 | + len = sizeof(uaddr); | ||
2434 | + addr = (struct sockaddr *)&uaddr; | ||
2435 | + } else | ||
2436 | +#endif | ||
2437 | + { | ||
2438 | + len = sizeof(saddr); | ||
2439 | + addr = (struct sockaddr *)&saddr; | ||
2440 | + } | ||
2441 | + fd = accept(s->listen_fd, addr, &len); | ||
2425 | if (fd < 0 && errno != EINTR) { | 2442 | if (fd < 0 && errno != EINTR) { |
2426 | return; | 2443 | return; |
2427 | } else if (fd >= 0) { | 2444 | } else if (fd >= 0) { |
@@ -2447,7 +2464,8 @@ static void tcp_chr_close(CharDriverState *chr) | @@ -2447,7 +2464,8 @@ static void tcp_chr_close(CharDriverState *chr) | ||
2447 | } | 2464 | } |
2448 | 2465 | ||
2449 | static CharDriverState *qemu_chr_open_tcp(const char *host_str, | 2466 | static CharDriverState *qemu_chr_open_tcp(const char *host_str, |
2450 | - int is_telnet) | 2467 | + int is_telnet, |
2468 | + int is_unix) | ||
2451 | { | 2469 | { |
2452 | CharDriverState *chr = NULL; | 2470 | CharDriverState *chr = NULL; |
2453 | TCPCharDriver *s = NULL; | 2471 | TCPCharDriver *s = NULL; |
@@ -2456,9 +2474,26 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, | @@ -2456,9 +2474,26 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, | ||
2456 | int is_waitconnect = 1; | 2474 | int is_waitconnect = 1; |
2457 | const char *ptr; | 2475 | const char *ptr; |
2458 | struct sockaddr_in saddr; | 2476 | struct sockaddr_in saddr; |
2477 | +#ifndef _WIN32 | ||
2478 | + struct sockaddr_un uaddr; | ||
2479 | +#endif | ||
2480 | + struct sockaddr *addr; | ||
2481 | + socklen_t addrlen; | ||
2459 | 2482 | ||
2460 | - if (parse_host_port(&saddr, host_str) < 0) | ||
2461 | - goto fail; | 2483 | +#ifndef _WIN32 |
2484 | + if (is_unix) { | ||
2485 | + addr = (struct sockaddr *)&uaddr; | ||
2486 | + addrlen = sizeof(uaddr); | ||
2487 | + if (parse_unix_path(&uaddr, host_str) < 0) | ||
2488 | + goto fail; | ||
2489 | + } else | ||
2490 | +#endif | ||
2491 | + { | ||
2492 | + addr = (struct sockaddr *)&saddr; | ||
2493 | + addrlen = sizeof(saddr); | ||
2494 | + if (parse_host_port(&saddr, host_str) < 0) | ||
2495 | + goto fail; | ||
2496 | + } | ||
2462 | 2497 | ||
2463 | ptr = host_str; | 2498 | ptr = host_str; |
2464 | while((ptr = strchr(ptr,','))) { | 2499 | while((ptr = strchr(ptr,','))) { |
@@ -2481,8 +2516,14 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, | @@ -2481,8 +2516,14 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, | ||
2481 | s = qemu_mallocz(sizeof(TCPCharDriver)); | 2516 | s = qemu_mallocz(sizeof(TCPCharDriver)); |
2482 | if (!s) | 2517 | if (!s) |
2483 | goto fail; | 2518 | goto fail; |
2484 | - | ||
2485 | - fd = socket(PF_INET, SOCK_STREAM, 0); | 2519 | + |
2520 | +#ifndef _WIN32 | ||
2521 | + if (is_unix) | ||
2522 | + fd = socket(PF_UNIX, SOCK_STREAM, 0); | ||
2523 | + else | ||
2524 | +#endif | ||
2525 | + fd = socket(PF_INET, SOCK_STREAM, 0); | ||
2526 | + | ||
2486 | if (fd < 0) | 2527 | if (fd < 0) |
2487 | goto fail; | 2528 | goto fail; |
2488 | 2529 | ||
@@ -2492,24 +2533,43 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, | @@ -2492,24 +2533,43 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, | ||
2492 | s->connected = 0; | 2533 | s->connected = 0; |
2493 | s->fd = -1; | 2534 | s->fd = -1; |
2494 | s->listen_fd = -1; | 2535 | s->listen_fd = -1; |
2536 | + s->is_unix = is_unix; | ||
2537 | + | ||
2538 | + chr->opaque = s; | ||
2539 | + chr->chr_write = tcp_chr_write; | ||
2540 | + chr->chr_add_read_handler = tcp_chr_add_read_handler; | ||
2541 | + chr->chr_close = tcp_chr_close; | ||
2542 | + | ||
2495 | if (is_listen) { | 2543 | if (is_listen) { |
2496 | /* allow fast reuse */ | 2544 | /* allow fast reuse */ |
2497 | - val = 1; | ||
2498 | - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); | 2545 | +#ifndef _WIN32 |
2546 | + if (is_unix) { | ||
2547 | + char path[109]; | ||
2548 | + strncpy(path, uaddr.sun_path, 108); | ||
2549 | + path[108] = 0; | ||
2550 | + unlink(path); | ||
2551 | + } else | ||
2552 | +#endif | ||
2553 | + { | ||
2554 | + val = 1; | ||
2555 | + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); | ||
2556 | + } | ||
2499 | 2557 | ||
2500 | - ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); | ||
2501 | - if (ret < 0) | 2558 | + ret = bind(fd, addr, addrlen); |
2559 | + if (ret < 0) | ||
2502 | goto fail; | 2560 | goto fail; |
2561 | + | ||
2503 | ret = listen(fd, 0); | 2562 | ret = listen(fd, 0); |
2504 | if (ret < 0) | 2563 | if (ret < 0) |
2505 | goto fail; | 2564 | goto fail; |
2565 | + | ||
2506 | s->listen_fd = fd; | 2566 | s->listen_fd = fd; |
2507 | qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr); | 2567 | qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr); |
2508 | if (is_telnet) | 2568 | if (is_telnet) |
2509 | s->do_telnetopt = 1; | 2569 | s->do_telnetopt = 1; |
2510 | } else { | 2570 | } else { |
2511 | for(;;) { | 2571 | for(;;) { |
2512 | - ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)); | 2572 | + ret = connect(fd, addr, addrlen); |
2513 | if (ret < 0) { | 2573 | if (ret < 0) { |
2514 | err = socket_error(); | 2574 | err = socket_error(); |
2515 | if (err == EINTR || err == EWOULDBLOCK) { | 2575 | if (err == EINTR || err == EWOULDBLOCK) { |
@@ -2530,10 +2590,6 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, | @@ -2530,10 +2590,6 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, | ||
2530 | qemu_set_fd_handler(s->fd, NULL, tcp_chr_connect, chr); | 2590 | qemu_set_fd_handler(s->fd, NULL, tcp_chr_connect, chr); |
2531 | } | 2591 | } |
2532 | 2592 | ||
2533 | - chr->opaque = s; | ||
2534 | - chr->chr_write = tcp_chr_write; | ||
2535 | - chr->chr_add_read_handler = tcp_chr_add_read_handler; | ||
2536 | - chr->chr_close = tcp_chr_close; | ||
2537 | if (is_listen && is_waitconnect) { | 2593 | if (is_listen && is_waitconnect) { |
2538 | printf("QEMU waiting for connection on: %s\n", host_str); | 2594 | printf("QEMU waiting for connection on: %s\n", host_str); |
2539 | tcp_chr_accept(chr); | 2595 | tcp_chr_accept(chr); |
@@ -2559,16 +2615,18 @@ CharDriverState *qemu_chr_open(const char *filename) | @@ -2559,16 +2615,18 @@ CharDriverState *qemu_chr_open(const char *filename) | ||
2559 | return qemu_chr_open_null(); | 2615 | return qemu_chr_open_null(); |
2560 | } else | 2616 | } else |
2561 | if (strstart(filename, "tcp:", &p)) { | 2617 | if (strstart(filename, "tcp:", &p)) { |
2562 | - return qemu_chr_open_tcp(p, 0); | 2618 | + return qemu_chr_open_tcp(p, 0, 0); |
2563 | } else | 2619 | } else |
2564 | if (strstart(filename, "telnet:", &p)) { | 2620 | if (strstart(filename, "telnet:", &p)) { |
2565 | - return qemu_chr_open_tcp(p, 1); | 2621 | + return qemu_chr_open_tcp(p, 1, 0); |
2566 | } else | 2622 | } else |
2567 | if (strstart(filename, "udp:", &p)) { | 2623 | if (strstart(filename, "udp:", &p)) { |
2568 | return qemu_chr_open_udp(p); | 2624 | return qemu_chr_open_udp(p); |
2569 | } else | 2625 | } else |
2570 | #ifndef _WIN32 | 2626 | #ifndef _WIN32 |
2571 | - if (strstart(filename, "file:", &p)) { | 2627 | + if (strstart(filename, "unix:", &p)) { |
2628 | + return qemu_chr_open_tcp(p, 0, 1); | ||
2629 | + } else if (strstart(filename, "file:", &p)) { | ||
2572 | return qemu_chr_open_file_out(p); | 2630 | return qemu_chr_open_file_out(p); |
2573 | } else if (strstart(filename, "pipe:", &p)) { | 2631 | } else if (strstart(filename, "pipe:", &p)) { |
2574 | return qemu_chr_open_pipe(p); | 2632 | return qemu_chr_open_pipe(p); |
@@ -2743,6 +2801,24 @@ int parse_host_port(struct sockaddr_in *saddr, const char *str) | @@ -2743,6 +2801,24 @@ int parse_host_port(struct sockaddr_in *saddr, const char *str) | ||
2743 | return 0; | 2801 | return 0; |
2744 | } | 2802 | } |
2745 | 2803 | ||
2804 | +int parse_unix_path(struct sockaddr_un *uaddr, const char *str) | ||
2805 | +{ | ||
2806 | + const char *p; | ||
2807 | + int len; | ||
2808 | + | ||
2809 | + len = MIN(108, strlen(str)); | ||
2810 | + p = strchr(str, ','); | ||
2811 | + if (p) | ||
2812 | + len = MIN(len, p - str); | ||
2813 | + | ||
2814 | + memset(uaddr, 0, sizeof(*uaddr)); | ||
2815 | + | ||
2816 | + uaddr->sun_family = AF_UNIX; | ||
2817 | + memcpy(uaddr->sun_path, str, len); | ||
2818 | + | ||
2819 | + return 0; | ||
2820 | +} | ||
2821 | + | ||
2746 | /* find or alloc a new VLAN */ | 2822 | /* find or alloc a new VLAN */ |
2747 | VLANState *qemu_find_vlan(int id) | 2823 | VLANState *qemu_find_vlan(int id) |
2748 | { | 2824 | { |
@@ -6955,6 +7031,7 @@ int main(int argc, char **argv) | @@ -6955,6 +7031,7 @@ int main(int argc, char **argv) | ||
6955 | vm_start(); | 7031 | vm_start(); |
6956 | } | 7032 | } |
6957 | } | 7033 | } |
7034 | + | ||
6958 | main_loop(); | 7035 | main_loop(); |
6959 | quit_timers(); | 7036 | quit_timers(); |
6960 | return 0; | 7037 | return 0; |