int exec_start_outgoing_migration(MigrationState *s, const char *command) { FILE *f; f = popen(command, "w"); if (f == NULL) { DPRINTF("Unable to popen exec target\n"); goto err_after_popen; } s->fd = fileno(f); if (s->fd == -1) { DPRINTF("Unable to retrieve file descriptor for popen'd handle\n"); goto err_after_open; } socket_set_nonblock(s->fd); s->opaque = qemu_popen(f, "w"); s->close = exec_close; s->get_error = file_errno; s->write = file_write; migrate_fd_connect(s); return 0; err_after_open: pclose(f); err_after_popen: return -1; }
bool socket_setopt_for_connect (net_socket sockfd) { if (!socket_set_nonblock(sockfd)) return false; /* prohibit nagle. */ { int bNoDelay = 1; setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char*)&bNoDelay, sizeof(int)); } { struct linger ling; ling.l_onoff=1; ling.l_linger=0; setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling)); } /*int bDontLinger = true; setsockopt(sockfd, SOL_SOCKET, SO_DONTLINGER, (char *)&bDontLinger, sizeof(int) ); int iSize = sizeof(int); int iRet = getsockopt(sockfd,SOL_SOCKET,SO_DONTLINGER,(char *)&bDontLinger, &iSize);*/ { int bKeepAlive = 1; setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (char*)&bKeepAlive, sizeof(int)); } return true; }
IO * http_init(int port) { struct sockaddr_in addr; int fd; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = INADDR_ANY; fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) die("socket on port %d failed\n", port); socket_set_reuseaddr(fd, 1); socket_set_nonblock(fd); if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) die("bind on port %d failed\n", port); if (listen(fd, 10) == -1) die("listen on port %d failed\n", port); return io_new_fd(fd); }
int tlc_exec_start_outgoing_migration(MigrationState *s, const char *command) { FILE *f; //int64_t test_timer_start, // test_timer_stop3, // test_timer_stop2, // test_timer_stop1; //test_timer_start = qemu_get_clock_ms(rt_clock); f = popen(command, "w"); if (f == NULL) { DPRINTF("Unable to popen exec target\n"); goto err_after_popen; } //test_timer_stop1 = qemu_get_clock_ms(rt_clock); //DREG{printf("exec: test_timer1: elasp = %" PRId64 " ms\n", test_timer_stop1 - test_timer_start); //fflush(stdout);} s->fd = fileno(f); if (s->fd == -1) { DPRINTF("Unable to retrieve file descriptor for popen'd handle\n"); goto err_after_open; } if(unlikely(mthread)){ //printf("exec_outgoing: set blocking\n"); fflush(stdout); socket_set_block(s->fd); } else{ printf("exec_outgoing: set NON blocking\n"); fflush(stdout); socket_set_nonblock(s->fd); } s->opaque = qemu_popen(f, "w"); //test_timer_stop2 = qemu_get_clock_ms(rt_clock); //DREG{printf("exec: test_timer2: elasp = %" PRId64 " ms\n", test_timer_stop2 - test_timer_stop1); //fflush(stdout);} s->close = exec_close; s->get_error = file_errno; s->write = file_write; migrate_fd_connect(s); //test_timer_stop3 = qemu_get_clock_ms(rt_clock); //DREG{printf("exec: test_timer3: elasp = %" PRId64 " ms\n", test_timer_stop3 - test_timer_stop2); //fflush(stdout);} return 0; err_after_open: pclose(f); err_after_popen: return -1; }
int unix_connect_opts(QemuOpts *opts, Error **errp, NonBlockingConnectHandler *callback, void *opaque) { struct sockaddr_un un; const char *path = qemu_opt_get(opts, "path"); ConnectState *connect_state = NULL; int sock, rc; if (NULL == path) { error_setg(errp, "unix connect: no path specified\n"); return -1; } sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); if (sock < 0) { error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); return -1; } if (callback != NULL) { connect_state = g_malloc0(sizeof(*connect_state)); connect_state->callback = callback; connect_state->opaque = opaque; socket_set_nonblock(sock); } memset(&un, 0, sizeof(un)); un.sun_family = AF_UNIX; snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); /* connect to peer */ do { rc = 0; if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) { rc = -socket_error(); } } while (rc == -EINTR); if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { connect_state->fd = sock; qemu_set_fd_handler2(sock, NULL, NULL, wait_for_connect, connect_state); return sock; } else if (rc >= 0) { /* non blocking socket immediate success, call callback */ if (callback != NULL) { callback(sock, opaque); } } if (rc < 0) { error_set_errno(errp, -rc, QERR_SOCKET_CONNECT_FAILED); close(sock); sock = -1; } g_free(connect_state); return sock; }
MigrationState *tcp_start_outgoing_migration(const char *host_port, int64_t bandwidth_limit, int detach, int blk, int inc) { struct sockaddr_in addr; FdMigrationState *s; int ret; if (parse_host_port(&addr, host_port) < 0) return NULL; s = qemu_mallocz(sizeof(*s)); s->get_error = socket_errno; s->write = socket_write; s->close = tcp_close; s->mig_state.cancel = migrate_fd_cancel; s->mig_state.get_status = migrate_fd_get_status; s->mig_state.release = migrate_fd_release; s->mig_state.blk = blk; s->mig_state.shared = inc; s->state = MIG_STATE_ACTIVE; s->mon_resume = NULL; s->bandwidth_limit = bandwidth_limit; s->fd = 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); 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) { dprintf("connect failed\n"); close(s->fd); qemu_free(s); return NULL; } else if (ret >= 0) migrate_fd_connect(s); return &s->mig_state; }
void socket_drainer_drain_and_close(int socket_fd) { if (socket_fd < 0) return; socket_set_nonblock(socket_fd); if (s_socket_drainer) { s_socket_drainer->drainAndClose(socket_fd); } else { android::base::DrainerObject drainerObject(socket_fd, 0, 0); } }
void process_incoming_migration(QEMUFile *f) { Coroutine *co = qemu_coroutine_create(process_incoming_migration_co); int fd = qemu_get_fd(f); assert(fd != -1); socket_set_nonblock(fd); qemu_coroutine_enter(co, f); }
MigrationState *exec_start_outgoing_migration(Monitor *mon, const char *command, int64_t bandwidth_limit, int detach, int blk, int inc) { FdMigrationState *s; FILE *f; s = qemu_mallocz(sizeof(*s)); f = popen(command, "w"); if (f == NULL) { dprintf("Unable to popen exec target\n"); goto err_after_alloc; } s->fd = fileno(f); if (s->fd == -1) { dprintf("Unable to retrieve file descriptor for popen'd handle\n"); goto err_after_open; } socket_set_nonblock(s->fd); s->opaque = qemu_popen(f, "w"); s->close = exec_close; s->get_error = file_errno; s->write = file_write; s->mig_state.cancel = migrate_fd_cancel; s->mig_state.get_status = migrate_fd_get_status; s->mig_state.release = migrate_fd_release; s->mig_state.blk = blk; s->mig_state.shared = inc; s->state = MIG_STATE_ACTIVE; s->mon = NULL; s->bandwidth_limit = bandwidth_limit; if (!detach) { migrate_fd_monitor_suspend(s, mon); } migrate_fd_connect(s); return &s->mig_state; err_after_open: pclose(f); err_after_alloc: qemu_free(s); return NULL; }
MigrationState *tcp_start_outgoing_migration(const char *host_port, int64_t bandwidth_limit, int detach) { SockAddress addr; FdMigrationState *s; int ret; if (parse_host_port(&addr, host_port) < 0) return NULL; s = g_malloc0(sizeof(*s)); s->get_error = socket_errno; s->write = socket_write; s->close = tcp_close; s->mig_state.cancel = migrate_fd_cancel; s->mig_state.get_status = migrate_fd_get_status; s->mig_state.release = migrate_fd_release; s->state = MIG_STATE_ACTIVE; s->mon_resume = NULL; s->bandwidth_limit = bandwidth_limit; s->fd = socket_create_inet(SOCKET_STREAM); if (s->fd == -1) { g_free(s); return NULL; } socket_set_nonblock(s->fd); if (!detach) migrate_fd_monitor_suspend(s); do { ret = socket_connect(s->fd, &addr); if (ret == -1) ret = -(s->get_error(s)); if (ret == -EINPROGRESS || ret == -EWOULDBLOCK || ret == -EAGAIN) qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s); } while (ret == -EINTR); if (ret < 0 && ret != -EINPROGRESS && ret != -EWOULDBLOCK && ret != -EAGAIN) { dprintf("connect failed\n"); socket_close(s->fd); g_free(s); return NULL; } else if (ret >= 0) migrate_fd_connect(s); return &s->mig_state; }
static void qlooper_io_init(Looper* looper, LoopIo* loopio, int fd, LoopIoFunc callback, void* opaque) { QLoopIo* io = qloopio_new(fd, callback, opaque, (QLooper*)looper); socket_set_nonblock(fd); loopio->clazz = (LoopIoClass*) &qlooper_io_class; loopio->impl = io; }
static int net_socket_connect_init(NetClientState *peer, const char *model, const char *name, const char *host_str) { NetSocketState *s; int fd, connected, ret, err; 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"); 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 || err == WSAEINVAL) { break; #endif } else { perror("connect"); closesocket(fd); return -1; } } else { connected = 1; break; } } s = net_socket_fd_init(peer, model, name, fd, connected); if (!s) return -1; snprintf(s->nc.info_str, sizeof(s->nc.info_str), "socket: connect to %s:%d", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); return 0; }
static int net_socket_listen_init(VLANState *vlan, const char *model, const char *name, const char *host_str) { NetSocketListenState *s; int fd, val, ret; struct sockaddr_in saddr; if (parse_host_port(&saddr, host_str) < 0) return -1; s = g_malloc0(sizeof(NetSocketListenState)); fd = qemu_socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { perror("socket"); g_free(s); 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)); if (ret < 0) { perror("bind"); g_free(s); closesocket(fd); return -1; } ret = listen(fd, 0); if (ret < 0) { perror("listen"); g_free(s); closesocket(fd); return -1; } s->vlan = vlan; s->model = g_strdup(model); s->name = name ? g_strdup(name) : NULL; s->fd = fd; qemu_set_fd_handler(fd, net_socket_accept, NULL, s); return 0; }
static int net_socket_listen_init(NetClientState *peer, const char *model, const char *name, const char *host_str) { NetClientState *nc; NetSocketState *s; struct sockaddr_in saddr; int fd, val, ret; if (parse_host_port(&saddr, host_str) < 0) return -1; 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)); if (ret < 0) { perror("bind"); closesocket(fd); return -1; } ret = listen(fd, 0); if (ret < 0) { perror("listen"); closesocket(fd); return -1; } nc = qemu_new_net_client(&net_socket_info, peer, model, name); s = DO_UPCAST(NetSocketState, nc, nc); s->fd = -1; s->listen_fd = fd; s->nc.link_down = true; qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s); return 0; }
SysChannel sys_channel_create_tcp_client( const char* hostname, int port ) { SysChannel channel = sys_channel_alloc(); channel->fd = socket_network_client( hostname, port, SOCKET_STREAM ); if (channel->fd < 0) { sys_channel_free(channel); return NULL; }; /* set to non-blocking and disable Nagle algorithm */ socket_set_nonblock( channel->fd ); socket_set_nodelay( channel->fd ); return channel; }
SyncSocket* syncsocket_connect(int fd, SockAddress* sockaddr, int timeout) { IoLooper* looper = NULL; int connect_status; SyncSocket* sync_socket; socket_set_nonblock(fd); for(;;) { connect_status = socket_connect(fd, sockaddr); if (connect_status >= 0) { // Connected. Create IoLooper for the helper. looper = iolooper_new(); break; } if (errno == EINPROGRESS || errno == EAGAIN || errno == EWOULDBLOCK) { // Connection is in progress. Wait till it's finished. looper = iolooper_new(); iolooper_add_write(looper, fd); connect_status = iolooper_wait(looper, timeout); if (connect_status > 0) { iolooper_del_write(looper, fd); } else { iolooper_free(looper); return NULL; } } else if (errno != EINTR) { return NULL; } } // We're now connected. Lets initialize SyncSocket instance // for this connection. sync_socket = malloc(sizeof(SyncSocket)); if (sync_socket == NULL) { derror("PANIC: not enough memory\n"); exit(1); } sync_socket->iolooper = looper; sync_socket->fd = fd; return sync_socket; }
/* Opens connection socket. * Param: * connector - Initialized AsyncSocketConnector instance. * Return: * 0 on success, or -1 on failure. */ static int _async_socket_connector_open_socket(AsyncSocketConnector* connector) { /* Open socket. */ connector->fd = socket_create_inet(SOCKET_STREAM); if (connector->fd < 0) { D("ASC %s: Unable to create socket: %d -> %s", _asc_socket_string(connector), errno, strerror(errno)); return -1; } /* Prepare for async I/O on the connector. */ socket_set_nonblock(connector->fd); T("ASC %s: Connector socket is opened with FD = %d", _asc_socket_string(connector), connector->fd); return 0; }
/******************************************************************************** * ADB server API *******************************************************************************/ int adb_server_init(int port) { if (!_adb_server_initialized) { /* Initialize the descriptor. */ memset(&_adb_server, 0, sizeof(_adb_server)); alist_init(&_adb_server.adb_hosts); alist_init(&_adb_server.adb_guests); alist_init(&_adb_server.pending_hosts); alist_init(&_adb_server.pending_guests); _adb_server.port = port; /* Create looper for an async I/O on the server. */ _adb_server.looper = looper_newCore(); if (_adb_server.looper == NULL) { E("Unable to create I/O looper for ADB server"); return -1; } /* Create loopback server socket for the ADB port. */ sock_address_init_inet(&_adb_server.socket_address, SOCK_ADDRESS_INET_LOOPBACK, port); _adb_server.so = socket_loopback_server(port, SOCKET_STREAM); if (_adb_server.so < 0) { E("Unable to create ADB server socket: %s", strerror(errno)); return -1; } /* Prepare server socket for I/O */ socket_set_nonblock(_adb_server.so); loopIo_init(_adb_server.io, _adb_server.looper, _adb_server.so, _on_server_socket_io, &_adb_server); loopIo_wantRead(_adb_server.io); D("ADB server has been initialized for port %d. Socket: %d", port, _adb_server.so); _adb_server_initialized = 1; } return 0; }
static void text_term_listen_read(void *opaque) { TextTermState *ts = opaque; struct TextTermClientState *tcs; struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); int new_sock; int i; new_sock = accept(ts->lsock, (struct sockaddr *)&addr, &addrlen); if (new_sock == -1) return; for (i = 0; i < MAX_CLIENTS; i++) if (!TCS_INUSE(ts->tcs[i])) break; if (i == MAX_CLIENTS) goto fail; if (ts->tcs[i] == NULL) { ts->tcs[i] = calloc(1, sizeof(struct TextTermClientState)); if (ts->tcs[i] == NULL) goto fail; } else { reset_tcs(ts->tcs[i]); } tcs = ts->tcs[i]; tcs->ts = ts; tcs->csock = new_sock; socket_set_nonblock(tcs->csock); ts->ds->set_fd_handler(tcs->csock, NULL, text_term_client_read, NULL, tcs); ts->ds->set_fd_error_handler(tcs->csock, text_term_client_error); return; fail: closesocket(new_sock); }
static int nbd_establish_connection(BlockDriverState *bs) { BDRVNBDState *s = bs->opaque; int sock; int ret; off_t size; size_t blocksize; if (s->host_spec[0] == '/') { sock = unix_socket_outgoing(s->host_spec); } else { sock = tcp_socket_outgoing_spec(s->host_spec); } /* Failed to establish connection */ if (sock < 0) { logout("Failed to establish connection to NBD server\n"); return -errno; } /* NBD handshake */ ret = nbd_receive_negotiate(sock, s->export_name, &s->nbdflags, &size, &blocksize); if (ret < 0) { logout("Failed to negotiate with the NBD server\n"); closesocket(sock); return ret; } /* Now that we're connected, set the socket to be non-blocking and * kick the reply mechanism. */ socket_set_nonblock(sock); qemu_aio_set_fd_handler(sock, nbd_reply_ready, NULL, nbd_have_request, s); s->sock = sock; s->size = size; s->blocksize = blocksize; logout("Established connection with NBD server\n"); return 0; }
static void glooper_io_init(Looper* looper, LoopIo* user, int fd, LoopIoFunc callback, void* opaque) { GLooper* gg = (GLooper*)looper; GLoopIo* io; ANEW0(io); io->fd = fd; io->callback = callback; io->opaque = opaque; io->looper = (GLooper*) looper; io->wanted = 0; io->ready = 0; socket_set_nonblock(fd); glooper_addIo(gg, io); user->impl = io; user->clazz = (LoopIoClass*) &gloopio_class; }
void http_accept(IO *io, int events, void *arg) { int cfd, fd = io_get_fd(io); struct sockaddr_in addr = { 0 }; size_t addr_len = sizeof(addr); IO *client; struct service *service = arg; if (events & IO_IN) { if ((cfd = accept(fd, (struct sockaddr *)&addr, &addr_len)) > -1) { socket_set_nonblock(cfd); client = io_new_fd(cfd); /* TODO: create conn */ struct conn *conn = conn_new(service, client); printf("--> accepted\n"); io_watch(client, IO_IN | IO_HUP, http_incoming, conn); } } }
static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, ConnectState *connect_state, Error **errp) { int sock, rc; *in_progress = false; sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if (sock < 0) { error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); return -1; } qemu_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (connect_state != NULL) { socket_set_nonblock(sock); } /* connect to peer */ do { rc = 0; if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) { rc = -socket_error(); } } while (rc == -EINTR); if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { connect_state->fd = sock; qemu_set_fd_handler2(sock, NULL, NULL, wait_for_connect, connect_state); *in_progress = true; } else if (rc < 0) { error_set_errno(errp, errno, QERR_SOCKET_CONNECT_FAILED); closesocket(sock); return -1; } return sock; }
static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, ConnectState *connect_state) { int sock, rc; *in_progress = false; sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if (sock < 0) { fprintf(stderr, "%s: socket(%s): %s\n", __func__, inet_strfamily(addr->ai_family), strerror(errno)); return -1; } qemu_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (connect_state != NULL) { socket_set_nonblock(sock); } /* connect to peer */ do { rc = 0; if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) { rc = -socket_error(); } } while (rc == -EINTR); if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { connect_state->fd = sock; qemu_set_fd_handler2(sock, NULL, NULL, wait_for_connect, connect_state); *in_progress = true; } else if (rc < 0) { closesocket(sock); return -1; } return sock; }
static int nbd_send_negotiate(int csock, off_t size, uint32_t flags) { char buf[8 + 8 + 8 + 128]; int rc; /* Negotiate [ 0 .. 7] passwd ("NBDMAGIC") [ 8 .. 15] magic (0x00420281861253) [16 .. 23] size [24 .. 27] flags [28 .. 151] reserved (0) */ socket_set_block(csock); rc = -EINVAL; TRACE("Beginning negotiation."); memcpy(buf, "NBDMAGIC", 8); cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL); cpu_to_be64w((uint64_t*)(buf + 16), size); cpu_to_be32w((uint32_t*)(buf + 24), flags | NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM | NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA); memset(buf + 28, 0, 124); if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { LOG("write failed"); goto fail; } TRACE("Negotiation succeeded."); rc = 0; fail: socket_set_nonblock(csock); return rc; }
int inet_connect_opts(QemuOpts *opts, Error **errp) { struct addrinfo ai,*res,*e; const char *addr; const char *port; char uaddr[INET6_ADDRSTRLEN+1]; char uport[33]; int sock,rc; bool block; memset(&ai,0, sizeof(ai)); ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; ai.ai_family = PF_UNSPEC; ai.ai_socktype = SOCK_STREAM; addr = qemu_opt_get(opts, "host"); port = qemu_opt_get(opts, "port"); block = qemu_opt_get_bool(opts, "block", 0); if (addr == NULL || port == NULL) { fprintf(stderr, "inet_connect: host and/or port not specified\n"); error_set(errp, QERR_SOCKET_CREATE_FAILED); return -1; } if (qemu_opt_get_bool(opts, "ipv4", 0)) ai.ai_family = PF_INET; if (qemu_opt_get_bool(opts, "ipv6", 0)) ai.ai_family = PF_INET6; /* lookup */ if (0 != (rc = getaddrinfo(addr, port, &ai, &res))) { fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port, gai_strerror(rc)); error_set(errp, QERR_SOCKET_CREATE_FAILED); return -1; } for (e = res; e != NULL; e = e->ai_next) { if (getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, uaddr,INET6_ADDRSTRLEN,uport,32, NI_NUMERICHOST | NI_NUMERICSERV) != 0) { fprintf(stderr,"%s: getnameinfo: oops\n", __FUNCTION__); continue; } sock = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol); if (sock < 0) { fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, inet_strfamily(e->ai_family), strerror(errno)); continue; } setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on)); if (!block) { socket_set_nonblock(sock); } /* connect to peer */ do { rc = 0; if (connect(sock, e->ai_addr, e->ai_addrlen) < 0) { rc = -socket_error(); } } while (rc == -EINTR); #ifdef _WIN32 if (!block && (rc == -EINPROGRESS || rc == -EWOULDBLOCK || rc == -WSAEALREADY)) { #else if (!block && (rc == -EINPROGRESS)) { #endif error_set(errp, QERR_SOCKET_CONNECT_IN_PROGRESS); } else if (rc < 0) { if (NULL == e->ai_next) fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__, inet_strfamily(e->ai_family), e->ai_canonname, uaddr, uport, strerror(errno)); closesocket(sock); sock = -1; continue; } freeaddrinfo(res); return sock; } error_set(errp, QERR_SOCKET_CONNECT_FAILED); freeaddrinfo(res); return -1; } int inet_dgram_opts(QemuOpts *opts) { struct addrinfo ai, *peer = NULL, *local = NULL; const char *addr; const char *port; char uaddr[INET6_ADDRSTRLEN+1]; char uport[33]; int sock = -1, rc; /* lookup peer addr */ memset(&ai,0, sizeof(ai)); ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; ai.ai_family = PF_UNSPEC; ai.ai_socktype = SOCK_DGRAM; addr = qemu_opt_get(opts, "host"); port = qemu_opt_get(opts, "port"); if (addr == NULL || strlen(addr) == 0) { addr = "localhost"; } if (port == NULL || strlen(port) == 0) { fprintf(stderr, "inet_dgram: port not specified\n"); return -1; } if (qemu_opt_get_bool(opts, "ipv4", 0)) ai.ai_family = PF_INET; if (qemu_opt_get_bool(opts, "ipv6", 0)) ai.ai_family = PF_INET6; if (0 != (rc = getaddrinfo(addr, port, &ai, &peer))) { fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port, gai_strerror(rc)); return -1; } /* lookup local addr */ memset(&ai,0, sizeof(ai)); ai.ai_flags = AI_PASSIVE; ai.ai_family = peer->ai_family; ai.ai_socktype = SOCK_DGRAM; addr = qemu_opt_get(opts, "localaddr"); port = qemu_opt_get(opts, "localport"); if (addr == NULL || strlen(addr) == 0) { addr = NULL; } if (!port || strlen(port) == 0) port = "0"; if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) { fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port, gai_strerror(rc)); return -1; } /* create socket */ sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol); if (sock < 0) { fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, inet_strfamily(peer->ai_family), strerror(errno)); goto err; } setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on)); /* bind socket */ if (getnameinfo((struct sockaddr*)local->ai_addr,local->ai_addrlen, uaddr,INET6_ADDRSTRLEN,uport,32, NI_NUMERICHOST | NI_NUMERICSERV) != 0) { fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__); goto err; } if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) { fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__, inet_strfamily(local->ai_family), uaddr, inet_getport(local)); goto err; } /* connect to peer */ if (getnameinfo((struct sockaddr*)peer->ai_addr, peer->ai_addrlen, uaddr, INET6_ADDRSTRLEN, uport, 32, NI_NUMERICHOST | NI_NUMERICSERV) != 0) { fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__); goto err; } if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) { fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__, inet_strfamily(peer->ai_family), peer->ai_canonname, uaddr, uport, strerror(errno)); goto err; } freeaddrinfo(local); freeaddrinfo(peer); return sock; err: if (-1 != sock) closesocket(sock); if (local) freeaddrinfo(local); if (peer) freeaddrinfo(peer); return -1; } /* compatibility wrapper */ static int inet_parse(QemuOpts *opts, const char *str) { const char *optstr, *h; char addr[64]; char port[33]; int pos; /* parse address */ if (str[0] == ':') { /* no host given */ addr[0] = '\0'; if (1 != sscanf(str,":%32[^,]%n",port,&pos)) { fprintf(stderr, "%s: portonly parse error (%s)\n", __FUNCTION__, str); return -1; } } else if (str[0] == '[') { /* IPv6 addr */ if (2 != sscanf(str,"[%64[^]]]:%32[^,]%n",addr,port,&pos)) { fprintf(stderr, "%s: ipv6 parse error (%s)\n", __FUNCTION__, str); return -1; } qemu_opt_set(opts, "ipv6", "on"); } else if (qemu_isdigit(str[0])) { /* IPv4 addr */ if (2 != sscanf(str,"%64[0-9.]:%32[^,]%n",addr,port,&pos)) { fprintf(stderr, "%s: ipv4 parse error (%s)\n", __FUNCTION__, str); return -1; } qemu_opt_set(opts, "ipv4", "on"); } else { /* hostname */ if (2 != sscanf(str,"%64[^:]:%32[^,]%n",addr,port,&pos)) { fprintf(stderr, "%s: hostname parse error (%s)\n", __FUNCTION__, str); return -1; } } qemu_opt_set(opts, "host", addr); qemu_opt_set(opts, "port", port); /* parse options */ optstr = str + pos; h = strstr(optstr, ",to="); if (h) qemu_opt_set(opts, "to", h+4); if (strstr(optstr, ",ipv4")) qemu_opt_set(opts, "ipv4", "on"); if (strstr(optstr, ",ipv6")) qemu_opt_set(opts, "ipv6", "on"); return 0; } int inet_listen(const char *str, char *ostr, int olen, int socktype, int port_offset, Error **errp) { QemuOpts *opts; char *optstr; int sock = -1; opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); if (inet_parse(opts, str) == 0) { sock = inet_listen_opts(opts, port_offset, errp); if (sock != -1 && ostr) { optstr = strchr(str, ','); if (qemu_opt_get_bool(opts, "ipv6", 0)) { snprintf(ostr, olen, "[%s]:%s%s", qemu_opt_get(opts, "host"), qemu_opt_get(opts, "port"), optstr ? optstr : ""); } else { snprintf(ostr, olen, "%s:%s%s", qemu_opt_get(opts, "host"), qemu_opt_get(opts, "port"), optstr ? optstr : ""); } } } else { error_set(errp, QERR_SOCKET_CREATE_FAILED); } qemu_opts_del(opts); return sock; }
int socket_create(const char *dest_ip, int dest_port, const char *src_ip, int src_port, int flags) { char *passive[] = {"::", "0.0.0.0"}; int sock = -1, pfamily, try_ok; sockname_t dest_name, src_name; /* If no source ip address is given, try :: and 0.0.0.0 (passive). */ for (try_ok = 0; try_ok < 2; try_ok++) { /* Resolve the ip addresses. */ socket_name(&dest_name, dest_ip ? dest_ip : passive[try_ok], dest_port); socket_name(&src_name, src_ip ? src_ip : passive[try_ok], src_port); if (src_ip || src_port) flags |= SOCKET_BIND; if (flags & SOCKET_CLIENT) pfamily = dest_name.family; else if (flags & SOCKET_SERVER) pfamily = src_name.family; else { errno = EADDRNOTAVAIL; return(-1); } /* Create the socket. */ if (flags & SOCKET_UDP) sock = socket(pfamily, SOCK_DGRAM, 0); else sock = socket(pfamily, SOCK_STREAM, 0); if (sock >= 0) break; } if (sock < 0) return(-2); allocsock(sock, 0); if (flags & SOCKET_NONBLOCK) socket_set_nonblock(sock, 1); /* Do the bind if necessary. */ if (flags & (SOCKET_SERVER|SOCKET_BIND)) { int yes = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); if (bind(sock, &src_name.u.addr, src_name.len) != 0) { killsock(sock); return(-3); } if (flags & SOCKET_SERVER) listen(sock, 50); } if (flags & SOCKET_CLIENT) { int i = -1; if ((i = findanysnum(sock)) != -1) { socklist[i].flags = (socklist[i].flags & ~SOCK_VIRTUAL) | SOCK_CONNECT | SOCK_PASS; socklist[i].host = strdup(dest_ip); socklist[i].port = dest_port; } if (connect(sock, &dest_name.u.addr, dest_name.len) != 0) { if (errno != EINPROGRESS) { killsock(sock); return(-4); } } } errno = 0; /* Yay, we're done. */ return(sock); }
int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, off_t *size, size_t *blocksize) { char buf[256]; uint64_t magic, s; uint16_t tmp; int rc; TRACE("Receiving negotiation."); socket_set_block(csock); rc = -EINVAL; if (read_sync(csock, buf, 8) != 8) { LOG("read failed"); goto fail; } buf[8] = '\0'; if (strlen(buf) == 0) { LOG("server connection closed"); goto fail; } TRACE("Magic is %c%c%c%c%c%c%c%c", qemu_isprint(buf[0]) ? buf[0] : '.', qemu_isprint(buf[1]) ? buf[1] : '.', qemu_isprint(buf[2]) ? buf[2] : '.', qemu_isprint(buf[3]) ? buf[3] : '.', qemu_isprint(buf[4]) ? buf[4] : '.', qemu_isprint(buf[5]) ? buf[5] : '.', qemu_isprint(buf[6]) ? buf[6] : '.', qemu_isprint(buf[7]) ? buf[7] : '.'); if (memcmp(buf, "NBDMAGIC", 8) != 0) { LOG("Invalid magic received"); goto fail; } if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) { LOG("read failed"); goto fail; } magic = be64_to_cpu(magic); TRACE("Magic is 0x%" PRIx64, magic); if (name) { uint32_t reserved = 0; uint32_t opt; uint32_t namesize; TRACE("Checking magic (opts_magic)"); if (magic != 0x49484156454F5054LL) { LOG("Bad magic received"); goto fail; } if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) { LOG("flags read failed"); goto fail; } *flags = be16_to_cpu(tmp) << 16; /* reserved for future use */ if (write_sync(csock, &reserved, sizeof(reserved)) != sizeof(reserved)) { LOG("write failed (reserved)"); goto fail; } /* write the export name */ magic = cpu_to_be64(magic); if (write_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) { LOG("write failed (magic)"); goto fail; } opt = cpu_to_be32(NBD_OPT_EXPORT_NAME); if (write_sync(csock, &opt, sizeof(opt)) != sizeof(opt)) { LOG("write failed (opt)"); goto fail; } namesize = cpu_to_be32(strlen(name)); if (write_sync(csock, &namesize, sizeof(namesize)) != sizeof(namesize)) { LOG("write failed (namesize)"); goto fail; } if (write_sync(csock, (char*)name, strlen(name)) != strlen(name)) { LOG("write failed (name)"); goto fail; } } else { TRACE("Checking magic (cli_magic)"); if (magic != 0x00420281861253LL) { LOG("Bad magic received"); goto fail; } } if (read_sync(csock, &s, sizeof(s)) != sizeof(s)) { LOG("read failed"); goto fail; } *size = be64_to_cpu(s); *blocksize = 1024; TRACE("Size is %" PRIu64, *size); if (!name) { if (read_sync(csock, flags, sizeof(*flags)) != sizeof(*flags)) { LOG("read failed (flags)"); goto fail; } *flags = be32_to_cpup(flags); } else { if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) { LOG("read failed (tmp)"); goto fail; } *flags |= be32_to_cpu(tmp); } if (read_sync(csock, &buf, 124) != 124) { LOG("read failed (buf)"); goto fail; } rc = 0; fail: socket_set_nonblock(csock); return rc; }
bool socket_setopt_for_listen (net_socket sockfd) { return socket_set_nonblock(sockfd) && set_reuseaddr(sockfd); }
static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr *localaddr) { struct ip_mreq imr; int fd; int val, ret; #ifdef __OpenBSD__ unsigned char loop; #else int loop; #endif if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) { fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) " "does not contain a multicast address\n", inet_ntoa(mcastaddr->sin_addr), (int)ntohl(mcastaddr->sin_addr.s_addr)); return -1; } fd = qemu_socket(PF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("socket(PF_INET, SOCK_DGRAM)"); return -1; } val = 1; ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); if (ret < 0) { perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)"); goto fail; } ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr)); if (ret < 0) { perror("bind"); goto fail; } /* Add host to multicast group */ imr.imr_multiaddr = mcastaddr->sin_addr; if (localaddr) { imr.imr_interface = *localaddr; } else { imr.imr_interface.s_addr = htonl(INADDR_ANY); } ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&imr, sizeof(struct ip_mreq)); if (ret < 0) { perror("setsockopt(IP_ADD_MEMBERSHIP)"); goto fail; } /* Force mcast msgs to loopback (eg. several QEMUs in same host */ loop = 1; ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const char *)&loop, sizeof(loop)); if (ret < 0) { perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)"); goto fail; } /* If a bind address is given, only send packets from that address */ if (localaddr != NULL) { ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (const char *)localaddr, sizeof(*localaddr)); if (ret < 0) { perror("setsockopt(IP_MULTICAST_IF)"); goto fail; } } socket_set_nonblock(fd); return fd; fail: if (fd >= 0) closesocket(fd); return -1; }