Ejemplo n.º 1
0
static int vsock_listen_saddr(VsockSocketAddress *vaddr,
                              Error **errp)
{
    struct sockaddr_vm svm;
    int slisten;

    if (!vsock_parse_vaddr_to_sockaddr(vaddr, &svm, errp)) {
        return -1;
    }

    slisten = qemu_socket(AF_VSOCK, SOCK_STREAM, 0);
    if (slisten < 0) {
        error_setg_errno(errp, errno, "Failed to create socket");
        return -1;
    }

    if (bind(slisten, (const struct sockaddr *)&svm, sizeof(svm)) != 0) {
        error_setg_errno(errp, errno, "Failed to bind socket");
        closesocket(slisten);
        return -1;
    }

    if (listen(slisten, 1) != 0) {
        error_setg_errno(errp, errno, "Failed to listen on socket");
        closesocket(slisten);
        return -1;
    }
    return slisten;
}
Ejemplo n.º 2
0
int unix_connect_opts(QemuOpts *opts)
{
    struct sockaddr_un un;
    const char *path = qemu_opt_get(opts, "path");
    int sock;

    if (NULL == path) {
        fprintf(stderr, "unix connect: no path specified\n");
        return -1;
    }

    sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("socket(unix)");
        return -1;
    }

    memset(&un, 0, sizeof(un));
    un.sun_family = AF_UNIX;
    snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
    if (connect(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
        fprintf(stderr, "connect(unix:%s): %s\n", path, strerror(errno));
	return -1;
    }

    if (sockets_debug)
        fprintf(stderr, "connect(unix:%s): OK\n", path);
    return sock;
}
Ejemplo n.º 3
0
static int inet_connect_addr(struct addrinfo *addr, Error **errp)
{
    int sock, rc;

    sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
    if (sock < 0) {
        error_setg_errno(errp, errno, "Failed to create socket");
        return -1;
    }
    socket_set_fast_reuse(sock);

    /* connect to peer */
    do {
        rc = 0;
        if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) {
            rc = -errno;
        }
    } while (rc == -EINTR);

    if (rc < 0) {
        error_setg_errno(errp, errno, "Failed to connect socket");
        closesocket(sock);
        return -1;
    }

    return sock;
}
Ejemplo n.º 4
0
static int vsock_connect_addr(const struct sockaddr_vm *svm, Error **errp)
{
    int sock, rc;

    sock = qemu_socket(AF_VSOCK, SOCK_STREAM, 0);
    if (sock < 0) {
        error_setg_errno(errp, errno, "Failed to create socket");
        return -1;
    }

    /* connect to peer */
    do {
        rc = 0;
        if (connect(sock, (const struct sockaddr *)svm, sizeof(*svm)) < 0) {
            rc = -errno;
        }
    } while (rc == -EINTR);

    if (rc < 0) {
        error_setg_errno(errp, errno, "Failed to connect socket");
        closesocket(sock);
        return -1;
    }

    return sock;
}
Ejemplo n.º 5
0
static int vsock_connect_addr(const struct sockaddr_vm *svm, bool *in_progress,
                              ConnectState *connect_state, Error **errp)
{
    int sock, rc;

    *in_progress = false;

    sock = qemu_socket(AF_VSOCK, SOCK_STREAM, 0);
    if (sock < 0) {
        error_setg_errno(errp, errno, "Failed to create socket");
        return -1;
    }
    if (connect_state != NULL) {
        qemu_set_nonblock(sock);
    }
    /* connect to peer */
    do {
        rc = 0;
        if (connect(sock, (const struct sockaddr *)svm, sizeof(*svm)) < 0) {
            rc = -errno;
        }
    } while (rc == -EINTR);

    if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) {
        connect_state->fd = sock;
        qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state);
        *in_progress = true;
    } else if (rc < 0) {
        error_setg_errno(errp, errno, "Failed to connect socket");
        closesocket(sock);
        return -1;
    }
    return sock;
}
Ejemplo n.º 6
0
static int icmp_send(struct socket *so, struct mbuf *m, int hlen)
{
    struct ip *ip = mtod(m, struct ip *);
    struct sockaddr_in addr;

    so->s = qemu_socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
    if (so->s == -1) {
        return -1;
    }

    so->so_m = m;
    so->so_faddr = ip->ip_dst;
    so->so_laddr = ip->ip_src;
    so->so_iptos = ip->ip_tos;
    so->so_type = IPPROTO_ICMP;
    so->so_state = SS_ISFCONNECTED;
    so->so_expire = curtime + SO_EXPIRE;

    addr.sin_family = AF_INET;
    addr.sin_addr = so->so_faddr;

    insque(so, &so->slirp->icmp);

    if (sendto(so->s, m->m_data + hlen, m->m_len - hlen, 0,
               (struct sockaddr *)&addr, sizeof(addr)) == -1) {
        DEBUG_MISC((dfd, "icmp_input icmp sendto tx errno = %d-%s\n",
                    errno, strerror(errno)));
        icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, strerror(errno));
        icmp_detach(so);
    }

    return 0;
}
Ejemplo n.º 7
0
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_setg_errno(errp, errno, "Failed to create socket");
        return -1;
    }
    socket_set_fast_reuse(sock);
    if (connect_state != NULL) {
        qemu_set_nonblock(sock);
    }
    /* connect to peer */
    do {
        rc = 0;
        if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) {
            rc = -errno;
        }
    } while (rc == -EINTR);

    if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) {
        connect_state->fd = sock;
        qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state);
        *in_progress = true;
    } else if (rc < 0) {
        error_setg_errno(errp, errno, "Failed to connect socket");
        closesocket(sock);
        return -1;
    }
    return sock;
}
Ejemplo n.º 8
0
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 (path == NULL) {
        error_setg(errp, "unix connect: no path specified");
        return -1;
    }

    sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
    if (sock < 0) {
        error_setg_errno(errp, errno, "Failed to create socket");
        return -1;
    }
    if (callback != NULL) {
        connect_state = g_malloc0(sizeof(*connect_state));
        connect_state->callback = callback;
        connect_state->opaque = opaque;
        qemu_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, NULL, opaque);
        }
    }

    if (rc < 0) {
        error_setg_errno(errp, -rc, "Failed to connect socket");
        close(sock);
        sock = -1;
    }

    g_free(connect_state);
    return sock;
}
Ejemplo n.º 9
0
static int create_fast_reuse_socket(struct addrinfo *e)
{
    int slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol);
    if (slisten < 0) {
        return -1;
    }
    socket_set_fast_reuse(slisten);
    return slisten;
}
Ejemplo n.º 10
0
int
udp_attach(struct socket *so)
{
  if((so->s = qemu_socket(AF_INET,SOCK_DGRAM,0)) != -1) {
    so->so_expire = curtime + SO_EXPIRE;
    insque(so, &so->slirp->udb);
  }
  return(so->s);
}
Ejemplo n.º 11
0
static int net_socket_udp_init(NetClientState *peer,
                                 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(peer, 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;
}
Ejemplo n.º 12
0
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;
}
Ejemplo n.º 13
0
int unix_listen_opts(QemuOpts *opts)
{
    struct sockaddr_un un;
    const char *path = qemu_opt_get(opts, "path");
    int sock, fd;

    sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("socket(unix)");
        return -1;
    }

    memset(&un, 0, sizeof(un));
    un.sun_family = AF_UNIX;
    if (path && strlen(path)) {
        snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
    } else {
        char *tmpdir = getenv("TMPDIR");
        snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX",
                 tmpdir ? tmpdir : "/tmp");
        /*
         * This dummy fd usage silences the mktemp() unsecure warning.
         * Using mkstemp() doesn't make things more secure here
         * though.  bind() complains about existing files, so we have
         * to unlink first and thus re-open the race window.  The
         * worst case possible is bind() failing, i.e. a DoS attack.
         */
        fd = mkstemp(un.sun_path); close(fd);
        qemu_opt_set(opts, "path", un.sun_path);
    }

    unlink(un.sun_path);
    if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
        fprintf(stderr, "bind(unix:%s): %s\n", un.sun_path, strerror(errno));
        goto err;
    }
    if (listen(sock, 1) < 0) {
        fprintf(stderr, "listen(unix:%s): %s\n", un.sun_path, strerror(errno));
        goto err;
    }

    if (sockets_debug)
        fprintf(stderr, "bind(unix:%s): OK\n", un.sun_path);
    return sock;

err:
    closesocket(sock);
    return -1;
}
Ejemplo n.º 14
0
static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp)
{
    struct sockaddr_un un;
    int sock, rc;
    size_t pathlen;

    if (saddr->path == NULL) {
        error_setg(errp, "unix connect: no path specified");
        return -1;
    }

    sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
    if (sock < 0) {
        error_setg_errno(errp, errno, "Failed to create socket");
        return -1;
    }

    pathlen = strlen(saddr->path);
    if (pathlen > sizeof(un.sun_path)) {
        error_setg(errp, "UNIX socket path '%s' is too long", saddr->path);
        error_append_hint(errp, "Path must be less than %zu bytes\n",
                          sizeof(un.sun_path));
        goto err;
    }

    memset(&un, 0, sizeof(un));
    un.sun_family = AF_UNIX;
    memcpy(un.sun_path, saddr->path, pathlen);

    /* connect to peer */
    do {
        rc = 0;
        if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) {
            rc = -errno;
        }
    } while (rc == -EINTR);

    if (rc < 0) {
        error_setg_errno(errp, -rc, "Failed to connect socket %s",
                         saddr->path);
        goto err;
    }

    return sock;

 err:
    close(sock);
    return -1;
}
Ejemplo n.º 15
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;
}
Ejemplo n.º 16
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;
}
Ejemplo n.º 17
0
struct socket *
udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
           u_int lport, int flags)
{
	struct sockaddr_in addr;
	struct socket *so;
	socklen_t addrlen = sizeof(struct sockaddr_in);

	so = socreate(slirp);
	if (!so) {
	    return NULL;
	}
	so->s = qemu_socket(AF_INET,SOCK_DGRAM,0);
	so->so_expire = curtime + SO_EXPIRE;
	insque(so, &slirp->udb);

	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = haddr;
	addr.sin_port = hport;

	if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) {
		udp_detach(so);
		return NULL;
	}
	socket_set_fast_reuse(so->s);

	getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
	so->so_fport = addr.sin_port;
	if (addr.sin_addr.s_addr == 0 ||
	    addr.sin_addr.s_addr == loopback_addr.s_addr) {
	   so->so_faddr = slirp->vhost_addr;
	} else {
	   so->so_faddr = addr.sin_addr;
	}
	so->so_lport = lport;
	so->so_laddr.s_addr = laddr;
	if (flags != SS_FACCEPTONCE)
	   so->so_expire = 0;

	so->so_state &= SS_PERSISTENT_MASK;
	so->so_state |= SS_ISFCONNECTED | flags;

	return so;
}
Ejemplo n.º 18
0
static int
connect_to_qemu(
    const char *host,
    const char *port
) {
    struct addrinfo hints;
    struct addrinfo *server;
    int ret;

    sock = qemu_socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        /* Error */
        fprintf(stderr, "Error opening socket!\n");
        return -1;
    }

    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = 0;
    hints.ai_protocol = 0;          /* Any protocol */

    ret = getaddrinfo(host, port, &hints, &server);

    if (ret != 0) {
        /* Error */
        fprintf(stderr, "getaddrinfo failed\n");
        return -1;
    }

    if (connect(sock, server->ai_addr, server->ai_addrlen) < 0) {
        /* Error */
        fprintf(stderr, "Could not connect\n");
        return -1;
    }
    if (verbose) {
        printf("Connected (sizeof Header=%zd)!\n", sizeof(VSCMsgHeader));
    }
    return sock;
}
Ejemplo n.º 19
0
int unix_start_incoming_migration(const char *path)
{
    struct sockaddr_un un;
    int sock;

    DPRINTF("Attempting to start an incoming migration\n");

    sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
    if (sock < 0) {
        fprintf(stderr, "Could not open unix socket: %s\n", strerror(errno));
        return -EINVAL;
    }

    memset(&un, 0, sizeof(un));
    un.sun_family = AF_UNIX;
    snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);

    unlink(un.sun_path);
    if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
        fprintf(stderr, "bind(unix:%s): %s\n", un.sun_path, strerror(errno));
        goto err;
    }
    if (listen(sock, 1) < 0) {
        fprintf(stderr, "listen(unix:%s): %s\n", un.sun_path, strerror(errno));
        goto err;
    }

    qemu_set_fd_handler2(sock, NULL, unix_accept_incoming_migration, NULL,
			 (void *)(intptr_t)sock);

    return 0;

err:
    close(sock);

    return -EINVAL;
}
Ejemplo n.º 20
0
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;
}
Ejemplo n.º 21
0
int qemu_http_init(void)
{
    QemuHttpState *state = (QemuHttpState *)qemu_mallocz(sizeof(QemuHttpState));
    ghttp_state = state;

    state->listen_fd = 0;
    memset(state->clients, 0, sizeof(state->clients));
    state->connections = 0;

    state->listen_fd = qemu_socket(AF_INET, SOCK_STREAM, 0);
    if (state->listen_fd < 0) {
        return 0;
    }

    const int on = 1;
    setsockopt(state->listen_fd, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on));

    struct sockaddr_in laddr;
    memset(&laddr, 0, sizeof(laddr));
    laddr.sin_family = AF_INET;
    laddr.sin_port = htons(DEFAULT_HTTP_PORT);
    laddr.sin_addr.s_addr = INADDR_ANY;

    if (bind(state->listen_fd, (struct sockaddr *)&laddr, sizeof(laddr)) == -1) {
        return 0;
    }

    if (listen(state->listen_fd, QEMU_MAX_HTTP_CONNECTIONS) == -1) {
        return 0;
    }

    fcntl_setfl(state->listen_fd, O_NONBLOCK);
    qemu_set_fd_handler(state->listen_fd, accept_handler, NULL, (void *)state);

    return 1;
}
Ejemplo n.º 22
0
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;
}
Ejemplo n.º 23
0
static int unix_listen_saddr(UnixSocketAddress *saddr,
                             Error **errp)
{
    struct sockaddr_un un;
    int sock, fd;
    char *pathbuf = NULL;
    const char *path;

    sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
    if (sock < 0) {
        error_setg_errno(errp, errno, "Failed to create Unix socket");
        return -1;
    }

    if (saddr->path && saddr->path[0]) {
        path = saddr->path;
    } else {
        const char *tmpdir = getenv("TMPDIR");
        tmpdir = tmpdir ? tmpdir : "/tmp";
        path = pathbuf = g_strdup_printf("%s/qemu-socket-XXXXXX", tmpdir);
    }

    if (strlen(path) > sizeof(un.sun_path)) {
        error_setg(errp, "UNIX socket path '%s' is too long", path);
        error_append_hint(errp, "Path must be less than %zu bytes\n",
                          sizeof(un.sun_path));
        goto err;
    }

    if (pathbuf != NULL) {
        /*
         * This dummy fd usage silences the mktemp() unsecure warning.
         * Using mkstemp() doesn't make things more secure here
         * though.  bind() complains about existing files, so we have
         * to unlink first and thus re-open the race window.  The
         * worst case possible is bind() failing, i.e. a DoS attack.
         */
        fd = mkstemp(pathbuf);
        if (fd < 0) {
            error_setg_errno(errp, errno,
                             "Failed to make a temporary socket %s", pathbuf);
            goto err;
        }
        close(fd);
    }

    if (unlink(path) < 0 && errno != ENOENT) {
        error_setg_errno(errp, errno,
                         "Failed to unlink socket %s", path);
        goto err;
    }

    memset(&un, 0, sizeof(un));
    un.sun_family = AF_UNIX;
    strncpy(un.sun_path, path, sizeof(un.sun_path));

    if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
        error_setg_errno(errp, errno, "Failed to bind socket to %s", path);
        goto err;
    }
    if (listen(sock, 1) < 0) {
        error_setg_errno(errp, errno, "Failed to listen on socket");
        goto err;
    }

    g_free(pathbuf);
    return sock;

err:
    g_free(pathbuf);
    closesocket(sock);
    return -1;
}
Ejemplo n.º 24
0
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;
    }
    if (sockets_debug) {
        fprintf(stderr, "%s: peer (%s:%s)\n", __FUNCTION__, addr, port);
        inet_print_addrinfo(__FUNCTION__, peer);
    }

    /* 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;
    }
    if (sockets_debug) {
        fprintf(stderr, "%s: local (%s:%s)\n", __FUNCTION__, addr, port);
        inet_print_addrinfo(__FUNCTION__, local);
    }

    /* 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;
}
Ejemplo n.º 25
0
int inet_connect_opts(QemuOpts *opts)
{
    struct addrinfo ai,*res,*e;
    const char *addr;
    const char *port;
    char uaddr[INET6_ADDRSTRLEN+1];
    char uport[33];
    int sock,rc;

    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");
    if (addr == NULL || port == NULL) {
        fprintf(stderr, "inet_connect: host and/or 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;

    /* lookup */
    if (0 != (rc = getaddrinfo(addr, port, &ai, &res))) {
        fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
                gai_strerror(rc));
	return -1;
    }
    if (sockets_debug)
        inet_print_addrinfo(__FUNCTION__, res);

    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));

        /* connect to peer */
        if (connect(sock,e->ai_addr,e->ai_addrlen) < 0) {
            if (sockets_debug || 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);
            continue;
        }
        if (sockets_debug)
            fprintf(stderr, "%s: connect(%s,%s,%s,%s): OK\n", __FUNCTION__,
                    inet_strfamily(e->ai_family),
                    e->ai_canonname, uaddr, uport);
        freeaddrinfo(res);
        return sock;
    }
    freeaddrinfo(res);
    return -1;
}
Ejemplo n.º 26
0
int inet_listen_opts(QemuOpts *opts, int port_offset)
{
    struct addrinfo ai,*res,*e;
    const char *addr;
    char port[33];
    char uaddr[INET6_ADDRSTRLEN+1];
    char uport[33];
    int slisten,rc,to,try_next;

    memset(&ai,0, sizeof(ai));
    ai.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
    ai.ai_family = PF_UNSPEC;
    ai.ai_socktype = SOCK_STREAM;

    if ((qemu_opt_get(opts, "host") == NULL) ||
        (qemu_opt_get(opts, "port") == NULL)) {
        fprintf(stderr, "%s: host and/or port not specified\n", __FUNCTION__);
        return -1;
    }
    pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port"));
    addr = qemu_opt_get(opts, "host");

    to = qemu_opt_get_number(opts, "to", 0);
    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 (port_offset)
        snprintf(port, sizeof(port), "%d", atoi(port) + port_offset);
    rc = getaddrinfo(strlen(addr) ? addr : NULL, port, &ai, &res);
    if (rc != 0) {
        fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
                gai_strerror(rc));
        return -1;
    }
    if (sockets_debug)
        inet_print_addrinfo(__FUNCTION__, res);

    /* create socket + bind */
    for (e = res; e != NULL; e = e->ai_next) {
        getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
		        uaddr,INET6_ADDRSTRLEN,uport,32,
		        NI_NUMERICHOST | NI_NUMERICSERV);
        slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol);
        if (slisten < 0) {
            fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
                    inet_strfamily(e->ai_family), strerror(errno));
            continue;
        }

        setsockopt(slisten,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
#ifdef IPV6_V6ONLY
        if (e->ai_family == PF_INET6) {
            /* listen on both ipv4 and ipv6 */
            setsockopt(slisten,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&off,
                sizeof(off));
        }
#endif

        for (;;) {
            if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) {
                if (sockets_debug)
                    fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__,
                        inet_strfamily(e->ai_family), uaddr, inet_getport(e));
                goto listen;
            }
            try_next = to && (inet_getport(e) <= to + port_offset);
            if (!try_next || sockets_debug)
                fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__,
                        inet_strfamily(e->ai_family), uaddr, inet_getport(e),
                        strerror(errno));
            if (try_next) {
                inet_setport(e, inet_getport(e) + 1);
                continue;
            }
            break;
        }
        closesocket(slisten);
    }
    fprintf(stderr, "%s: FAILED\n", __FUNCTION__);
    freeaddrinfo(res);
    return -1;

listen:
    if (listen(slisten,1) != 0) {
        perror("listen");
        closesocket(slisten);
        freeaddrinfo(res);
        return -1;
    }
    snprintf(uport, sizeof(uport), "%d", inet_getport(e) - port_offset);
    qemu_opt_set(opts, "host", uaddr);
    qemu_opt_set(opts, "port", uport);
    qemu_opt_set(opts, "ipv6", (e->ai_family == PF_INET6) ? "on" : "off");
    qemu_opt_set(opts, "ipv4", (e->ai_family != PF_INET6) ? "on" : "off");
    freeaddrinfo(res);
    return slisten;
}
Ejemplo n.º 27
0
Archivo: socket.c Proyecto: djs55/qemu
/*
 * Listen for incoming TCP connections
 */
struct socket *
tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
           u_int lport, int flags)
{
	struct sockaddr_in addr;
	struct socket *so;
	int s, opt = 1;
	socklen_t addrlen = sizeof(addr);
	memset(&addr, 0, addrlen);

	DEBUG_CALL("tcp_listen");
	DEBUG_ARG("haddr = %x", haddr);
	DEBUG_ARG("hport = %d", hport);
	DEBUG_ARG("laddr = %x", laddr);
	DEBUG_ARG("lport = %d", lport);
	DEBUG_ARG("flags = %x", flags);

	so = socreate(slirp);
	if (!so) {
	  return NULL;
	}

	/* Don't tcp_attach... we don't need so_snd nor so_rcv */
	if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {
		free(so);
		return NULL;
	}
	insque(so, &slirp->tcb);

	/*
	 * SS_FACCEPTONCE sockets must time out.
	 */
	if (flags & SS_FACCEPTONCE)
	   so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;

	so->so_state &= SS_PERSISTENT_MASK;
	so->so_state |= (SS_FACCEPTCONN | flags);
	so->so_lport = lport; /* Kept in network format */
	so->so_laddr.s_addr = laddr; /* Ditto */

	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = haddr;
	addr.sin_port = hport;

	if (((s = qemu_socket(AF_INET,SOCK_STREAM,0)) < 0) ||
	    (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
	    (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
	    (listen(s,1) < 0)) {
		int tmperrno = errno; /* Don't clobber the real reason we failed */

		close(s);
		sofree(so);
		/* Restore the real errno */
#ifdef _WIN32
		WSASetLastError(tmperrno);
#else
		errno = tmperrno;
#endif
		return NULL;
	}
	setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));

	getsockname(s,(struct sockaddr *)&addr,&addrlen);
	so->so_fport = addr.sin_port;
	if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
	   so->so_faddr = slirp->vhost_addr;
	else
	   so->so_faddr = addr.sin_addr;

	so->s = s;
	return so;
}
Ejemplo n.º 28
0
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;
}
Ejemplo n.º 29
0
static void test_io_channel_ipv4(bool async)
{
    SocketAddress *listen_addr = g_new0(SocketAddress, 1);
    SocketAddress *connect_addr = g_new0(SocketAddress, 1);

    listen_addr->type = SOCKET_ADDRESS_TYPE_INET;
    listen_addr->u.inet = (InetSocketAddress) {
        .host = g_strdup("127.0.0.1"),
        .port = NULL, /* Auto-select */
    };

    connect_addr->type = SOCKET_ADDRESS_TYPE_INET;
    connect_addr->u.inet = (InetSocketAddress) {
        .host = g_strdup("127.0.0.1"),
        .port = NULL, /* Filled in later */
    };

    test_io_channel(async, listen_addr, connect_addr, false);

    qapi_free_SocketAddress(listen_addr);
    qapi_free_SocketAddress(connect_addr);
}


static void test_io_channel_ipv4_sync(void)
{
    return test_io_channel_ipv4(false);
}


static void test_io_channel_ipv4_async(void)
{
    return test_io_channel_ipv4(true);
}


static void test_io_channel_ipv6(bool async)
{
    SocketAddress *listen_addr = g_new0(SocketAddress, 1);
    SocketAddress *connect_addr = g_new0(SocketAddress, 1);

    listen_addr->type = SOCKET_ADDRESS_TYPE_INET;
    listen_addr->u.inet = (InetSocketAddress) {
        .host = g_strdup("::1"),
        .port = NULL, /* Auto-select */
    };

    connect_addr->type = SOCKET_ADDRESS_TYPE_INET;
    connect_addr->u.inet = (InetSocketAddress) {
        .host = g_strdup("::1"),
        .port = NULL, /* Filled in later */
    };

    test_io_channel(async, listen_addr, connect_addr, false);

    qapi_free_SocketAddress(listen_addr);
    qapi_free_SocketAddress(connect_addr);
}


static void test_io_channel_ipv6_sync(void)
{
    return test_io_channel_ipv6(false);
}


static void test_io_channel_ipv6_async(void)
{
    return test_io_channel_ipv6(true);
}


#ifndef _WIN32
static void test_io_channel_unix(bool async)
{
    SocketAddress *listen_addr = g_new0(SocketAddress, 1);
    SocketAddress *connect_addr = g_new0(SocketAddress, 1);

#define TEST_SOCKET "test-io-channel-socket.sock"
    listen_addr->type = SOCKET_ADDRESS_TYPE_UNIX;
    listen_addr->u.q_unix.path = g_strdup(TEST_SOCKET);

    connect_addr->type = SOCKET_ADDRESS_TYPE_UNIX;
    connect_addr->u.q_unix.path = g_strdup(TEST_SOCKET);

    test_io_channel(async, listen_addr, connect_addr, true);

    qapi_free_SocketAddress(listen_addr);
    qapi_free_SocketAddress(connect_addr);
    g_assert(g_file_test(TEST_SOCKET, G_FILE_TEST_EXISTS) == FALSE);
}


static void test_io_channel_unix_sync(void)
{
    return test_io_channel_unix(false);
}


static void test_io_channel_unix_async(void)
{
    return test_io_channel_unix(true);
}

static void test_io_channel_unix_fd_pass(void)
{
    SocketAddress *listen_addr = g_new0(SocketAddress, 1);
    SocketAddress *connect_addr = g_new0(SocketAddress, 1);
    QIOChannel *src, *dst;
    int testfd;
    int fdsend[3];
    int *fdrecv = NULL;
    size_t nfdrecv = 0;
    size_t i;
    char bufsend[12], bufrecv[12];
    struct iovec iosend[1], iorecv[1];

#define TEST_SOCKET "test-io-channel-socket.sock"
#define TEST_FILE "test-io-channel-socket.txt"

    testfd = open(TEST_FILE, O_RDWR|O_TRUNC|O_CREAT, 0700);
    g_assert(testfd != -1);
    fdsend[0] = testfd;
    fdsend[1] = testfd;
    fdsend[2] = testfd;

    listen_addr->type = SOCKET_ADDRESS_TYPE_UNIX;
    listen_addr->u.q_unix.path = g_strdup(TEST_SOCKET);

    connect_addr->type = SOCKET_ADDRESS_TYPE_UNIX;
    connect_addr->u.q_unix.path = g_strdup(TEST_SOCKET);

    test_io_channel_setup_sync(listen_addr, connect_addr, &src, &dst);

    memcpy(bufsend, "Hello World", G_N_ELEMENTS(bufsend));

    iosend[0].iov_base = bufsend;
    iosend[0].iov_len = G_N_ELEMENTS(bufsend);

    iorecv[0].iov_base = bufrecv;
    iorecv[0].iov_len = G_N_ELEMENTS(bufrecv);

    g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
    g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));

    qio_channel_writev_full(src,
                            iosend,
                            G_N_ELEMENTS(iosend),
                            fdsend,
                            G_N_ELEMENTS(fdsend),
                            &error_abort);

    qio_channel_readv_full(dst,
                           iorecv,
                           G_N_ELEMENTS(iorecv),
                           &fdrecv,
                           &nfdrecv,
                           &error_abort);

    g_assert(nfdrecv == G_N_ELEMENTS(fdsend));
    /* Each recvd FD should be different from sent FD */
    for (i = 0; i < nfdrecv; i++) {
        g_assert_cmpint(fdrecv[i], !=, testfd);
    }
    /* Each recvd FD should be different from each other */
    g_assert_cmpint(fdrecv[0], !=, fdrecv[1]);
    g_assert_cmpint(fdrecv[0], !=, fdrecv[2]);
    g_assert_cmpint(fdrecv[1], !=, fdrecv[2]);

    /* Check the I/O buf we sent at the same time matches */
    g_assert(memcmp(bufsend, bufrecv, G_N_ELEMENTS(bufsend)) == 0);

    /* Write some data into the FD we received */
    g_assert(write(fdrecv[0], bufsend, G_N_ELEMENTS(bufsend)) ==
             G_N_ELEMENTS(bufsend));

    /* Read data from the original FD and make sure it matches */
    memset(bufrecv, 0, G_N_ELEMENTS(bufrecv));
    g_assert(lseek(testfd, 0, SEEK_SET) == 0);
    g_assert(read(testfd, bufrecv, G_N_ELEMENTS(bufrecv)) ==
             G_N_ELEMENTS(bufrecv));
    g_assert(memcmp(bufsend, bufrecv, G_N_ELEMENTS(bufsend)) == 0);

    object_unref(OBJECT(src));
    object_unref(OBJECT(dst));
    qapi_free_SocketAddress(listen_addr);
    qapi_free_SocketAddress(connect_addr);
    unlink(TEST_SOCKET);
    unlink(TEST_FILE);
    close(testfd);
    for (i = 0; i < nfdrecv; i++) {
        close(fdrecv[i]);
    }
    g_free(fdrecv);
}

static void test_io_channel_unix_listen_cleanup(void)
{
    QIOChannelSocket *ioc;
    struct sockaddr_un un;
    int sock;

#define TEST_SOCKET "test-io-channel-socket.sock"

    ioc = qio_channel_socket_new();

    /* Manually bind ioc without calling the qio api to avoid setting
     * the LISTEN feature */
    sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
    memset(&un, 0, sizeof(un));
    un.sun_family = AF_UNIX;
    snprintf(un.sun_path, sizeof(un.sun_path), "%s", TEST_SOCKET);
    unlink(TEST_SOCKET);
    bind(sock, (struct sockaddr *)&un, sizeof(un));
    ioc->fd = sock;
    ioc->localAddrLen = sizeof(ioc->localAddr);
    getsockname(sock, (struct sockaddr *)&ioc->localAddr,
                &ioc->localAddrLen);

    g_assert(g_file_test(TEST_SOCKET, G_FILE_TEST_EXISTS));
    object_unref(OBJECT(ioc));
    g_assert(g_file_test(TEST_SOCKET, G_FILE_TEST_EXISTS));

    unlink(TEST_SOCKET);
}
Ejemplo n.º 30
0
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;
}