Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
working with separate cli parms
- lots of debug messages
- uses unix1 and unix2
- want to unify into single parm like
  unix=/tmp/path1:/tmp/path2
  • Loading branch information
rschmied committed Apr 23, 2021
1 parent b1cffef commit 73f0211
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 4 deletions.
4 changes: 4 additions & 0 deletions include/qemu/sockets.h
Expand Up @@ -46,6 +46,10 @@ int socket_listen(SocketAddress *addr, int num, Error **errp);
void socket_listen_cleanup(int fd, Error **errp);
int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp);

int parse_uds_path_pair(struct sockaddr_un *spath, struct sockaddr_un *dpath, const char *str,
Error **errp);


/* Old, ipv4 only bits. Don't use for new code. */
int parse_host_port(struct sockaddr_in *saddr, const char *str,
Error **errp);
Expand Down
22 changes: 22 additions & 0 deletions net/net.c
Expand Up @@ -121,6 +121,28 @@ int parse_host_port(struct sockaddr_in *saddr, const char *str,
return ret;
}

int parse_uds_path_pair(struct sockaddr_un *spath, struct sockaddr_un *dpath, const char *str,
Error **errp)
{
gchar **substrings;
int ret = 0;

substrings = g_strsplit(str, ":", 2);
if (!substrings || !substrings[0] || !substrings[1]) {
error_setg(errp, "unix domain socket path pair '%s' doesn't contain ':' "
"separating path1 from path2", str);
ret = -1;
goto out;
}

strncpy(spath->sun_path, substrings[0], sizeof(spath->sun_path) - 1);
strncpy(dpath->sun_path, substrings[1], sizeof(dpath->sun_path) - 1);

out:
g_strfreev(substrings);
return ret;
}

char *qemu_mac_strdup_printf(const uint8_t *macaddr)
{
return g_strdup_printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
Expand Down
98 changes: 94 additions & 4 deletions net/socket.c
Expand Up @@ -40,7 +40,8 @@ typedef struct NetSocketState {
int fd;
SocketReadState rs;
unsigned int send_index; /* number of bytes sent (only SOCK_STREAM) */
struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */
struct sockaddr_in dgram_dst; /* contains inet host and port destination if connectionless (SOCK_DGRAM) */
struct sockaddr_un unix_dst; /* contains the UDS pathname if using Unix Domain sockets */
IOHandler *send_fn; /* differs between SOCK_STREAM/SOCK_DGRAM */
bool read_poll; /* waiting to receive data? */
bool write_poll; /* waiting to transmit data? */
Expand Down Expand Up @@ -118,13 +119,20 @@ static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf,
NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
ssize_t ret;

// fprintf(stderr, "### net_socket_receive_dgram1 family %d\n", (int)s->dgram_dst.sin_family);

do {
if (s->dgram_dst.sin_family != AF_UNIX) {
ret = qemu_sendto(s->fd, buf, size, 0,
(struct sockaddr *)&s->dgram_dst,
sizeof(s->dgram_dst));
// fprintf(stderr, "### net_socket_receive_dgram1 %zu\n", size);
} else {
ret = send(s->fd, buf, size, 0);
// fprintf(stderr, "### net_socket_receive_dgram2 %zu\n", size);
// ret = send(s->fd, buf, size, 0);
ret = qemu_sendto(s->fd, buf, size, 0,
(struct sockaddr *)&s->unix_dst,
sizeof(s->unix_dst));
}
} while (ret == -1 && errno == EINTR);

Expand Down Expand Up @@ -348,6 +356,7 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
return NULL;
}
sa_type = sa->type;
// fprintf(stderr, "#### net_socket_fd_init_dgram %d\n", sa_type);
qapi_free_SocketAddress(sa);

/* fd passed: multicast: "learn" dgram_dst address from bound address and save it
Expand Down Expand Up @@ -395,6 +404,9 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
if (sa_type == SOCKET_ADDRESS_TYPE_UNIX) {
s->dgram_dst.sin_family = AF_UNIX;
}
// if (sa_type == SOCKET_ADDRESS_TYPE_UNIX) {
// s->unix_dst.sun_family = AF_UNIX;
// }

snprintf(nc->info_str, sizeof(nc->info_str),
"socket: fd=%d %s", fd, SocketAddressType_str(sa_type));
Expand Down Expand Up @@ -463,6 +475,7 @@ static NetSocketState *net_socket_fd_init(NetClientState *peer,
closesocket(fd);
return NULL;
}
// fprintf(stderr, "#### net_socket_fd_init %d\n", so_type);
switch(so_type) {
case SOCK_DGRAM:
return net_socket_fd_init_dgram(peer, model, name, fd, is_connected,
Expand Down Expand Up @@ -650,6 +663,70 @@ static int net_socket_mcast_init(NetClientState *peer,

}

static int net_socket_unix_init(NetClientState *peer,
const char *model,
const char *name,
const char *unix_paths,
Error **errp)
{
NetSocketState *s;
int fd, ret;
struct sockaddr_un from_addr, to_addr;

from_addr.sun_family = AF_UNIX;
to_addr.sun_family = AF_UNIX;

ret = parse_uds_path_pair(&from_addr, &to_addr, unix_paths, errp);
if (ret < 0) {
error_setg_errno(errp, errno,
"### tbd uds_path_pair result");
return -1;
}

if (unlink(to_addr.sun_path) < 0 && errno != ENOENT) {
error_setg_errno(errp, errno,
"Failed to unlink socket %s", to_addr.sun_path);
return -1;
}

fd = qemu_socket(PF_UNIX, SOCK_DGRAM, 0);
if (fd < 0) {
error_setg_errno(errp, errno, "can't create unix datagram socket");
return -1;
}

ret = socket_set_fast_reuse(fd);
if (ret < 0) {
error_setg_errno(errp, errno,
"can't set socket option SO_REUSEADDR");
closesocket(fd);
return -1;
}
ret = bind(fd, (struct sockaddr *)&to_addr, sizeof(to_addr));
if (ret < 0) {
error_setg_errno(errp, errno, "can't bind \"%s\" to unix domain socket",
to_addr.sun_path);
closesocket(fd);
return -1;
}
qemu_set_nonblock(fd);

// fprintf(stderr, "#### net_socket_unix_init\n");

s = net_socket_fd_init(peer, model, name, fd, 0, NULL, errp);
if (!s) {
return -1;
}

s->unix_dst = from_addr;

// fprintf(stderr, "#### net_socket_unix_init2\n");

snprintf(s->nc.info_str, sizeof(s->nc.info_str),
"socket: unix=%s:%s", to_addr.sun_path, from_addr.sun_path);
return 0;
}

static int net_socket_udp_init(NetClientState *peer,
const char *model,
const char *name,
Expand All @@ -661,6 +738,9 @@ static int net_socket_udp_init(NetClientState *peer,
int fd, ret;
struct sockaddr_in laddr, raddr;

// fprintf(stderr, "#### net_socket_udp_init %s\n", lhost); // --> 10456
// fprintf(stderr, "#### net_socket_udp_init %s\n", rhost); // --> 10123

if (parse_host_port(&laddr, lhost, errp) < 0) {
return -1;
}
Expand Down Expand Up @@ -713,8 +793,8 @@ int net_init_socket(const Netdev *netdev, const char *name,
sock = &netdev->u.socket;

if (sock->has_fd + sock->has_listen + sock->has_connect + sock->has_mcast +
sock->has_udp != 1) {
error_setg(errp, "exactly one of listen=, connect=, mcast= or udp="
sock->has_udp + sock->has_q_unix != 1) {
error_setg(errp, "exactly one of listen=, connect=, mcast=, udp= or unix="
" is required");
return -1;
}
Expand Down Expand Up @@ -770,6 +850,16 @@ int net_init_socket(const Netdev *netdev, const char *name,
return 0;
}

if (sock->has_q_unix) {
// fprintf(stderr, "unix %s\n", sock->q_unix);

if (net_socket_unix_init(peer, "socket", name, sock->q_unix,
errp) < 0) {
return -1;
}
return 0;
}

assert(sock->has_udp);
if (!sock->has_localaddr) {
error_setg(errp, "localaddr= is mandatory with udp=");
Expand Down
4 changes: 4 additions & 0 deletions qapi/net.json
Expand Up @@ -268,6 +268,9 @@
#
# @udp: UDP unicast address and port number
#
# @unix: Unix Domain socket filenames from/to separated by a colon
#
#
# Since: 1.2
##
{ 'struct': 'NetdevSocketOptions',
Expand All @@ -277,6 +280,7 @@
'*connect': 'str',
'*mcast': 'str',
'*localaddr': 'str',
'*unix': 'str',
'*udp': 'str' } }

##
Expand Down
5 changes: 5 additions & 0 deletions qemu-options.hx
Expand Up @@ -2522,6 +2522,11 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
"-netdev socket,id=str[,fd=h][,udp=host:port][,localaddr=host:port]\n"
" configure a network backend to connect to another network\n"
" using an UDP tunnel\n"
#ifndef _WIN32
"-netdev socket,id=str[,fd=h][,unix=path_from:path_to]\n"
" configure a network backend to connect to another network\n"
" using a Unix domain socket\n"
#endif
#ifdef CONFIG_VDE
"-netdev vde,id=str[,sock=socketpath][,port=n][,group=groupname][,mode=octalmode]\n"
" configure a network backend to connect to port 'n' of a vde switch\n"
Expand Down

0 comments on commit 73f0211

Please sign in to comment.