diff -ru qemu-kvm-0.13.0/migration-tcp.c qemu-kvm-0.13.0-patched/migration-tcp.c --- qemu-kvm-0.13.0/migration-tcp.c 2010-10-15 00:06:47.000000000 +0900 +++ qemu-kvm-0.13.0-patched/migration-tcp.c 2011-07-26 03:13:21.000000000 +0900 @@ -83,13 +83,10 @@ int blk, int inc) { - struct sockaddr_in addr; FdMigrationState *s; + int fd; int ret; - if (parse_host_port(&addr, host_port) < 0) - return NULL; - s = qemu_mallocz(sizeof(*s)); s->get_error = socket_errno; @@ -105,32 +102,22 @@ s->state = MIG_STATE_ACTIVE; s->mon = NULL; s->bandwidth_limit = bandwidth_limit; - s->fd = qemu_socket(PF_INET, SOCK_STREAM, 0); - if (s->fd == -1) { - qemu_free(s); - return NULL; - } - - socket_set_nonblock(s->fd); if (!detach) { migrate_fd_monitor_suspend(s, mon); } - do { - ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr)); - if (ret == -1) - ret = -(s->get_error(s)); - - if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) - qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s); - } while (ret == -EINTR); - - if (ret < 0 && ret != -EINPROGRESS && ret != -EWOULDBLOCK) { + ret = tcp_client_start(host_port, &fd); + s->fd = fd; + if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) { + DPRINTF("connect in progress"); + qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s); + } else if (ret < 0) { DPRINTF("connect failed\n"); migrate_fd_error(s); - } else if (ret >= 0) + } else { migrate_fd_connect(s); + } return &s->mig_state; } @@ -171,25 +158,14 @@ int tcp_start_incoming_migration(const char *host_port) { - struct sockaddr_in addr; - int val; + int ret; int s; - if (parse_host_port(&addr, host_port) < 0) { - fprintf(stderr, "invalid host/port combination: %s\n", host_port); - return -EINVAL; + ret = tcp_server_start(host_port, &s); + if (ret < 0) { + return ret; } - s = qemu_socket(PF_INET, SOCK_STREAM, 0); - if (s == -1) - return -socket_error(); - - val = 1; - setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); - - if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) - goto err; - if (listen(s, 1) == -1) goto err; diff -ru qemu-kvm-0.13.0/net/socket.c qemu-kvm-0.13.0-patched/net/socket.c --- qemu-kvm-0.13.0/net/socket.c 2010-10-15 00:06:47.000000000 +0900 +++ qemu-kvm-0.13.0-patched/net/socket.c 2011-07-26 03:13:21.000000000 +0900 @@ -167,12 +167,10 @@ return -1; } - val = 1; - ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, - (const char *)&val, sizeof(val)); + ret = socket_set_reuseaddr(fd); if (ret < 0) { - perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)"); - goto fail; + perror("socket_set_reuseaddr"); + goto fail; } ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr)); @@ -378,28 +376,13 @@ const char *host_str) { NetSocketListenState *s; - int fd, val, ret; - struct sockaddr_in saddr; - - if (parse_host_port(&saddr, host_str) < 0) - return -1; + int fd, ret; s = qemu_mallocz(sizeof(NetSocketListenState)); - fd = qemu_socket(PF_INET, SOCK_STREAM, 0); - if (fd < 0) { - perror("socket"); - return -1; - } - socket_set_nonblock(fd); - - /* allow fast reuse */ - val = 1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); - - ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); + ret = tcp_server_start(host_str, &fd); if (ret < 0) { - perror("bind"); + fprintf(stderr, "tcp_server_start: %s\n", strerror(ret)); return -1; } ret = listen(fd, 0); @@ -421,41 +404,18 @@ const char *host_str) { NetSocketState *s; - int fd, connected, ret, err; + int fd, connected, ret; struct sockaddr_in saddr; - if (parse_host_port(&saddr, host_str) < 0) - return -1; - - fd = qemu_socket(PF_INET, SOCK_STREAM, 0); - if (fd < 0) { - perror("socket"); + ret = tcp_client_start(host_str, &fd); + if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) { + connected = 0; + } else if (ret < 0) { + closesocket(fd); return -1; - } - socket_set_nonblock(fd); - - connected = 0; - for(;;) { - ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)); - if (ret < 0) { - err = socket_error(); - if (err == EINTR || err == EWOULDBLOCK) { - } else if (err == EINPROGRESS) { - break; -#ifdef _WIN32 - } else if (err == WSAEALREADY) { - break; -#endif - } else { - perror("connect"); - closesocket(fd); - return -1; - } - } else { - connected = 1; - break; - } - } + } else { + connected = 1; + } s = net_socket_fd_init(vlan, model, name, fd, connected); if (!s) return -1; qemu-kvm-0.13.0-patched/netだけに発見: socket.c.orig diff -ru qemu-kvm-0.13.0/net.c qemu-kvm-0.13.0-patched/net.c --- qemu-kvm-0.13.0/net.c 2010-10-15 00:06:47.000000000 +0900 +++ qemu-kvm-0.13.0-patched/net.c 2011-07-26 03:13:21.000000000 +0900 @@ -93,6 +93,111 @@ return 0; } +static int tcp_server_bind(int fd, struct addrinfo *rp) +{ + int ret; + + socket_set_reuseaddr(fd); + + ret = bind(fd, rp->ai_addr, rp->ai_addrlen); + + if (ret == -1) { + ret = -socket_error(); + } + + return ret; +} + +static int tcp_client_connect(int fd, struct addrinfo *rp) +{ + int ret; + + do { + ret = connect(fd, rp->ai_addr, rp->ai_addrlen); + if (ret == -1) { + ret = -socket_error(); + } + } while (ret == -EINTR); + + return ret; +} + +static int tcp_start_common(const char *str, int *fd, bool server) +{ + char hostname[512]; + const char *service; + const char *name; + struct addrinfo hints; + struct addrinfo *result, *rp; + int s; + int sfd; + int ret = -EINVAL; + + *fd = -1; + service = str; + if (get_str_sep(hostname, sizeof(hostname), &service, ':') < 0) { + return -EINVAL; + } + if (server && strlen(hostname) == 0) { + name = NULL; + } else { + name = hostname; + } + + /* Obtain address(es) matching host/port */ + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_STREAM; /* Datagram socket */ + + if (server) { + hints.ai_flags = AI_PASSIVE; + } + + s = getaddrinfo(name, service, &hints, &result); + if (s != 0) { + fprintf(stderr, "qemu: getaddrinfo: %s\n", gai_strerror(s)); + return -EINVAL; + } + + /* getaddrinfo() returns a list of address structures. + Try each address until we successfully bind/connect). + If socket(2) (or bind/connect(2)) fails, we (close the socket + and) try the next address. */ + + for (rp = result; rp != NULL; rp = rp->ai_next) { + sfd = qemu_socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (sfd == -1) { + ret = -errno; + continue; + } + socket_set_nonblock(sfd); + if (server) { + ret = tcp_server_bind(sfd, rp); + } else { + ret = tcp_client_connect(sfd, rp); + } + if (ret >= 0 || ret == -EINPROGRESS || ret == -EWOULDBLOCK) { + *fd = sfd; + break; /* Success */ + } + close(sfd); + } + + freeaddrinfo(result); + return ret; +} + +int tcp_server_start(const char *str, int *fd) +{ + return tcp_start_common(str, fd, true); +} + +int tcp_client_start(const char *str, int *fd) +{ + return tcp_start_common(str, fd, false); +} + int parse_host_src_port(struct sockaddr_in *haddr, struct sockaddr_in *saddr, const char *input_str) diff -ru qemu-kvm-0.13.0/os-posix.c qemu-kvm-0.13.0-patched/os-posix.c --- qemu-kvm-0.13.0/os-posix.c 2011-07-28 22:00:29.000000000 +0900 +++ qemu-kvm-0.13.0-patched/os-posix.c 2011-07-28 22:00:56.000000000 +0900 @@ -27,6 +27,7 @@ #include #include #include +#include #include /*needed for MAP_POPULATE before including qemu-options.h */ #include diff -ru qemu-kvm-0.13.0/os-posix.c qemu-kvm-0.13.0-patched/os-posix.c --- qemu-kvm-0.13.0/os-posix.c 2010-10-15 00:06:47.000000000 +0900 +++ qemu-kvm-0.13.0-patched/os-posix.c 2011-07-26 03:15:28.000000000 +0900 @@ -329,3 +329,10 @@ { setvbuf(stdout, NULL, _IOLBF, 0); } + +int socket_set_reuseaddr(int fd) +{ + int val = 1; + /* allow fast reuse */ + return setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); +} diff -ru qemu-kvm-0.13.0/os-win32.c qemu-kvm-0.13.0-patched/os-win32.c --- qemu-kvm-0.13.0/os-win32.c 2010-10-15 00:06:47.000000000 +0900 +++ qemu-kvm-0.13.0-patched/os-win32.c 2011-07-26 03:15:56.000000000 +0900 @@ -219,3 +219,9 @@ { fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno)); } + +int socket_set_reuseaddr(int fd) +{ + /* Nothing, this is the default windows behaviour */ + return 0; +} diff -ru qemu-kvm-0.13.0/qemu-sockets.c qemu-kvm-0.13.0-patched/qemu-sockets.c --- qemu-kvm-0.13.0/qemu-sockets.c 2010-10-15 00:06:47.000000000 +0900 +++ qemu-kvm-0.13.0-patched/qemu-sockets.c 2011-07-26 03:13:55.000000000 +0900 @@ -168,7 +168,7 @@ continue; } - setsockopt(slisten,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on)); + socket_set_reuseaddr(slisten); #ifdef IPV6_V6ONLY if (e->ai_family == PF_INET6) { /* listen on both ipv4 and ipv6 */ @@ -265,7 +265,7 @@ inet_strfamily(e->ai_family), strerror(errno)); continue; } - setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on)); + socket_set_reuseaddr(sock); /* connect to peer */ if (connect(sock,e->ai_addr,e->ai_addrlen) < 0) { @@ -358,7 +358,7 @@ inet_strfamily(peer->ai_family), strerror(errno)); goto err; } - setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on)); + socket_set_reuseaddr(sock); /* bind socket */ if (getnameinfo((struct sockaddr*)local->ai_addr,local->ai_addrlen, diff -ru qemu-kvm-0.13.0/qemu_socket.h qemu-kvm-0.13.0-patched/qemu_socket.h --- qemu-kvm-0.13.0/qemu_socket.h 2010-10-15 00:06:47.000000000 +0900 +++ qemu-kvm-0.13.0-patched/qemu_socket.h 2011-07-26 03:13:55.000000000 +0900 @@ -35,6 +35,7 @@ int qemu_socket(int domain, int type, int protocol); int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen); void socket_set_nonblock(int fd); +int socket_set_reuseaddr(int fd); int send_all(int fd, const void *buf, int len1); /* New, ipv6-ready socket helper functions, see qemu-sockets.c */ @@ -58,4 +59,7 @@ const char *str); int socket_init(void); +int tcp_client_start(const char *str, int *fd); +int tcp_server_start(const char *str, int *fd); + #endif /* QEMU_SOCKET_H */ diff -ru qemu-kvm-0.13.0/tests/linux-test.c qemu-kvm-0.13.0-patched/tests/linux-test.c --- qemu-kvm-0.13.0/tests/linux-test.c 2010-10-15 00:06:47.000000000 +0900 +++ qemu-kvm-0.13.0-patched/tests/linux-test.c 2011-07-26 03:13:55.000000000 +0900 @@ -284,8 +284,7 @@ /* server socket */ fd = chk_error(socket(PF_INET, SOCK_STREAM, 0)); - val = 1; - chk_error(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))); + chk_error(socket_set_reuseaddr(fd)); sockaddr.sin_family = AF_INET; sockaddr.sin_port = htons(TESTPORT);