@@ -33,6 +33,9 @@
#include "qemu/sockets.h"
#include "qemu/iov.h"
#include "qemu/main-loop.h"
+#ifdef CONFIG_UDST
+#include "udst.h"
+#endif
typedef struct NetSocketState {
NetClientState nc;
@@ -49,6 +52,14 @@ typedef struct NetSocketState {
static void net_socket_accept(void *opaque);
static void net_socket_writable(void *opaque);
+#ifdef CONFIG_UDST
+static int noop(void *us, uint8_t *buf)
+{
+ return 0;
+}
+#endif
+
+
static void net_socket_update_fd_handler(NetSocketState *s)
{
qemu_set_fd_handler(s->fd,
@@ -113,6 +124,8 @@ static ssize_t net_socket_receive(NetClientState *nc, const uint8_t *buf, size_t
return size;
}
+#ifndef CONFIG_UDST
+
static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf, size_t size)
{
NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
@@ -130,6 +143,7 @@ static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf,
}
return ret;
}
+#endif
static void net_socket_send_completed(NetClientState *nc, ssize_t len)
{
@@ -189,6 +203,8 @@ static void net_socket_send(void *opaque)
}
}
+#ifndef CONFIG_UDST
+
static void net_socket_send_dgram(void *opaque)
{
NetSocketState *s = opaque;
@@ -208,6 +224,7 @@ static void net_socket_send_dgram(void *opaque)
net_socket_read_poll(s, false);
}
}
+#endif
static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr *localaddr)
{
@@ -309,7 +326,85 @@ static void net_socket_cleanup(NetClientState *nc)
s->listen_fd = -1;
}
}
+#ifdef CONFIG_UDST
+static NetUdstState *net_socket_fd_init_dgram(NetClientState *peer,
+ const char *model,
+ const char *name,
+ int fd, int is_connected)
+{
+ struct sockaddr_in saddr;
+ int newfd;
+ socklen_t saddr_len = sizeof(saddr);
+ NetClientState *nc;
+ NetUdstState *s;
+ /* fd passed: multicast: "learn" dgram_dst address from bound address and save it
+ * Because this may be "shared" socket from a "master" process, datagrams would be recv()
+ * by ONLY ONE process: we must "clone" this dgram socket --jjo
+ */
+
+ 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);
+ 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;
+ }
+ }
+
+ fprintf(stderr,
+ "qemu: init udst for fd=%d\n",
+ fd);
+ nc = qemu_new_udst_net_client(name, peer);
+
+ s = DO_UPCAST(NetUdstState, nc, nc);
+
+ s->offset = 0;
+
+ qemu_net_finalize_udst_init(s,
+ &noop,
+ NULL,
+ fd);
+
+ /* mcast: save bound address as dst */
+ if (is_connected) {
+ s->dgram_dst = g_memdup(&saddr, sizeof(struct sockaddr_in));
+ s->dst_size = sizeof(struct sockaddr_in);
+ snprintf(nc->info_str, sizeof(nc->info_str),
+ "socket: fd=%d (cloned mcast=%s:%d)",
+ fd, inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+ } else {
+ /* This will be overwritten later if we have a dst */
+ s->dgram_dst = NULL;
+ s->dst_size = 0;
+ snprintf(nc->info_str, sizeof(nc->info_str),
+ "socket: fd=%d", fd);
+ }
+
+ return s;
+
+err:
+ closesocket(fd);
+ return NULL;
+}
+#else
static NetClientInfo net_dgram_socket_info = {
.type = NET_CLIENT_DRIVER_SOCKET,
.size = sizeof(NetSocketState),
@@ -386,6 +481,7 @@ err:
closesocket(fd);
return NULL;
}
+#endif
static void net_socket_connect(void *opaque)
{
@@ -430,7 +526,7 @@ static NetSocketState *net_socket_fd_init_stream(NetClientState *peer,
return s;
}
-static NetSocketState *net_socket_fd_init(NetClientState *peer,
+static void *net_socket_fd_init(NetClientState *peer,
const char *model, const char *name,
int fd, int is_connected)
{
@@ -567,7 +663,7 @@ static int net_socket_connect_init(NetClientState *peer,
break;
}
}
- s = net_socket_fd_init(peer, model, name, fd, connected);
+ s = net_socket_fd_init_stream(peer, model, name, fd, connected);
if (!s)
return -1;
snprintf(s->nc.info_str, sizeof(s->nc.info_str),
@@ -582,7 +678,11 @@ static int net_socket_mcast_init(NetClientState *peer,
const char *host_str,
const char *localaddr_str)
{
+#ifdef CONFIG_UDST
+ NetUdstState *s;
+#else
NetSocketState *s;
+#endif
int fd;
struct sockaddr_in saddr;
struct in_addr localaddr, *param_localaddr;
@@ -602,11 +702,15 @@ static int net_socket_mcast_init(NetClientState *peer,
if (fd < 0)
return -1;
- s = net_socket_fd_init(peer, model, name, fd, 0);
+ s = net_socket_fd_init_dgram(peer, model, name, fd, 0);
if (!s)
return -1;
-
+#ifdef CONFIG_UDST
+ s->dgram_dst = g_memdup(&saddr, sizeof(struct sockaddr_in));
+ s->dst_size = sizeof(struct sockaddr_in);
+#else
s->dgram_dst = saddr;
+#endif
snprintf(s->nc.info_str, sizeof(s->nc.info_str),
"socket: mcast=%s:%d",
@@ -621,7 +725,11 @@ static int net_socket_udp_init(NetClientState *peer,
const char *rhost,
const char *lhost)
{
+#ifdef CONFIG_UDST
+ NetUdstState *s;
+#else
NetSocketState *s;
+#endif
int fd, ret;
struct sockaddr_in laddr, raddr;
@@ -652,12 +760,17 @@ static int net_socket_udp_init(NetClientState *peer,
}
qemu_set_nonblock(fd);
- s = net_socket_fd_init(peer, model, name, fd, 0);
+ s = net_socket_fd_init_dgram(peer, model, name, fd, 0);
if (!s) {
return -1;
}
+#ifdef CONFIG_UDST
+ s->dgram_dst = g_memdup(&raddr, sizeof(struct sockaddr_in));
+ s->dst_size = sizeof(struct sockaddr_in);
+#else
s->dgram_dst = raddr;
+#endif
snprintf(s->nc.info_str, sizeof(s->nc.info_str),
"socket: udp=%s:%d",