uint8_t buf1[4096];
const uint8_t *buf;
- size = recv(s->fd, (void *)buf1, sizeof(buf1), 0);
+ size = qemu_recv(s->fd, buf1, sizeof(buf1), 0);
if (size < 0) {
err = socket_error();
if (err != EWOULDBLOCK)
NetSocketState *s = opaque;
int size;
- size = recv(s->fd, (void *)s->buf, sizeof(s->buf), 0);
+ size = qemu_recv(s->fd, s->buf, sizeof(s->buf), 0);
if (size < 0)
return;
if (size == 0) {
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),
+ 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;
+ return -1;
}
fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
(const char *)&val, sizeof(val));
if (ret < 0) {
- perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
- goto fail;
+ perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
+ goto fail;
}
ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr));
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;
+ perror("setsockopt(IP_ADD_MEMBERSHIP)");
+ goto fail;
}
/* Force mcast msgs to loopback (eg. several QEMUs in same host */
- val = 1;
+ loop = 1;
ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
- (const char *)&val, sizeof(val));
+ (const char *)&loop, sizeof(loop));
if (ret < 0) {
- perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
- goto fail;
+ 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, localaddr, sizeof(*localaddr));
+ ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
+ (const char *)localaddr, sizeof(*localaddr));
if (ret < 0) {
perror("setsockopt(IP_MULTICAST_IF)");
goto fail;
*/
if (is_connected) {
- if (getsockname(fd, (struct sockaddr *) &saddr, &saddr_len) == 0) {
- /* must be bound */
- if (saddr.sin_addr.s_addr==0) {
- fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, cannot setup multicast dst addr\n",
- fd);
- return NULL;
- }
- /* clone dgram socket */
- newfd = net_socket_mcast_create(&saddr, NULL);
- if (newfd < 0) {
- /* error already reported by net_socket_mcast_create() */
- close(fd);
- return NULL;
- }
- /* clone newfd to fd, close newfd */
- dup2(newfd, fd);
- close(newfd);
-
- } else {
- fprintf(stderr, "qemu: error: init_dgram: fd=%d failed getsockname(): %s\n",
- fd, strerror(errno));
- return NULL;
- }
+ if (getsockname(fd, (struct sockaddr *) &saddr, &saddr_len) == 0) {
+ /* must be bound */
+ if (saddr.sin_addr.s_addr == 0) {
+ fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, "
+ "cannot setup multicast dst addr\n", fd);
+ goto err;
+ }
+ /* clone dgram socket */
+ newfd = net_socket_mcast_create(&saddr, NULL);
+ if (newfd < 0) {
+ /* error already reported by net_socket_mcast_create() */
+ goto err;
+ }
+ /* clone newfd to fd, close newfd */
+ dup2(newfd, fd);
+ close(newfd);
+
+ } else {
+ fprintf(stderr,
+ "qemu: error: init_dgram: fd=%d failed getsockname(): %s\n",
+ fd, strerror(errno));
+ goto err;
+ }
}
nc = qemu_new_net_client(&net_dgram_socket_info, vlan, NULL, model, name);
snprintf(nc->info_str, sizeof(nc->info_str),
- "socket: fd=%d (%s mcast=%s:%d)",
- fd, is_connected ? "cloned" : "",
- inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+ "socket: fd=%d (%s mcast=%s:%d)",
+ fd, is_connected ? "cloned" : "",
+ inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
s = DO_UPCAST(NetSocketState, nc, nc);
if (is_connected) s->dgram_dst=saddr;
return s;
+
+err:
+ closesocket(fd);
+ return NULL;
}
static void net_socket_connect(void *opaque)
if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type,
(socklen_t *)&optlen)< 0) {
- fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n", fd);
- return NULL;
+ fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n",
+ fd);
+ closesocket(fd);
+ return NULL;
}
switch(so_type) {
case SOCK_DGRAM:
}
}
s1 = net_socket_fd_init(s->vlan, s->model, s->name, fd, 1);
- if (!s1) {
- closesocket(fd);
- } else {
+ if (s1) {
snprintf(s1->nc.info_str, sizeof(s1->nc.info_str),
"socket: connection from %s:%d",
inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
if (parse_host_port(&saddr, host_str) < 0)
return -1;
- s = qemu_mallocz(sizeof(NetSocketListenState));
+ 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);
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 = qemu_strdup(model);
- s->name = name ? qemu_strdup(name) : NULL;
+ 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;
} else if (err == EINPROGRESS) {
break;
#ifdef _WIN32
- } else if (err == WSAEALREADY) {
+ } else if (err == WSAEALREADY || err == WSAEINVAL) {
break;
#endif
} else {
fd = net_socket_mcast_create(&saddr, param_localaddr);
if (fd < 0)
- return -1;
+ return -1;
s = net_socket_fd_init(vlan, model, name, fd, 0);
if (!s)
}
+static int net_socket_udp_init(VLANState *vlan,
+ const char *model,
+ const char *name,
+ const char *rhost,
+ const char *lhost)
+{
+ NetSocketState *s;
+ int fd, val, ret;
+ struct sockaddr_in laddr, raddr;
+
+ if (parse_host_port(&laddr, lhost) < 0) {
+ return -1;
+ }
+
+ if (parse_host_port(&raddr, rhost) < 0) {
+ 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)");
+ closesocket(fd);
+ return -1;
+ }
+ ret = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
+ if (ret < 0) {
+ perror("bind");
+ closesocket(fd);
+ return -1;
+ }
+
+ s = net_socket_fd_init(vlan, model, name, fd, 0);
+ if (!s) {
+ return -1;
+ }
+
+ s->dgram_dst = raddr;
+
+ snprintf(s->nc.info_str, sizeof(s->nc.info_str),
+ "socket: udp=%s:%d",
+ inet_ntoa(raddr.sin_addr), ntohs(raddr.sin_port));
+ return 0;
+}
+
int net_init_socket(QemuOpts *opts,
Monitor *mon,
const char *name,
qemu_opt_get(opts, "connect") ||
qemu_opt_get(opts, "mcast") ||
qemu_opt_get(opts, "localaddr")) {
- error_report("listen=, connect=, mcast= and localaddr= is invalid with fd=\n");
+ error_report("listen=, connect=, mcast= and localaddr= is invalid with fd=");
return -1;
}
}
if (!net_socket_fd_init(vlan, "socket", name, fd, 1)) {
- close(fd);
return -1;
}
} else if (qemu_opt_get(opts, "listen")) {
qemu_opt_get(opts, "connect") ||
qemu_opt_get(opts, "mcast") ||
qemu_opt_get(opts, "localaddr")) {
- error_report("fd=, connect=, mcast= and localaddr= is invalid with listen=\n");
+ error_report("fd=, connect=, mcast= and localaddr= is invalid with listen=");
return -1;
}
qemu_opt_get(opts, "listen") ||
qemu_opt_get(opts, "mcast") ||
qemu_opt_get(opts, "localaddr")) {
- error_report("fd=, listen=, mcast= and localaddr= is invalid with connect=\n");
+ error_report("fd=, listen=, mcast= and localaddr= is invalid with connect=");
return -1;
}
if (net_socket_mcast_init(vlan, "socket", name, mcast, localaddr) == -1) {
return -1;
}
+ } else if (qemu_opt_get(opts, "udp")) {
+ const char *udp, *localaddr;
+
+ if (qemu_opt_get(opts, "fd") ||
+ qemu_opt_get(opts, "connect") ||
+ qemu_opt_get(opts, "listen") ||
+ qemu_opt_get(opts, "mcast")) {
+ error_report("fd=, connect=, listen=\
+ and mcast= is invalid with udp=");
+ return -1;
+ }
+
+ udp = qemu_opt_get(opts, "udp");
+ localaddr = qemu_opt_get(opts, "localaddr");
+ if (localaddr == NULL) {
+ error_report("localaddr= is mandatory with udp=");
+ return -1;
+ }
+
+ if (net_socket_udp_init(vlan, "udp", name, udp, localaddr) == -1) {
+ return -1;
+ }
} else {
- error_report("-socket requires fd=, listen=, connect= or mcast=");
+ error_report("-socket requires fd=, listen=, \
+ connect=, mcast= or udp=");
return -1;
}
-
return 0;
}