コード例 #1
0
ファイル: qemu-sockets.c プロジェクト: 16aug/nvmeqemu
static void inet_print_addrinfo(const char *tag, struct addrinfo *res)
{
    struct addrinfo *e;
    char uaddr[INET6_ADDRSTRLEN+1];
    char uport[33];

    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);
        fprintf(stderr,"%s: getaddrinfo: family %s, host %s, port %s\n",
                tag, inet_strfamily(e->ai_family), uaddr, uport);
    }
}
コード例 #2
0
ファイル: qemu-sockets.c プロジェクト: RafaelRMachado/qemu
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;
}
コード例 #3
0
ファイル: qemu-sockets.c プロジェクト: 16aug/nvmeqemu
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;
}
コード例 #4
0
ファイル: qemu-sockets.c プロジェクト: 16aug/nvmeqemu
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;
}
コード例 #5
0
ファイル: qemu-sockets.c プロジェクト: 16aug/nvmeqemu
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;
}
コード例 #6
0
ファイル: qemu-sockets.c プロジェクト: AsherBond/qemu-kvm-mq
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;
}