diff --git a/cmds/recv.c b/cmds/recv.c index 71c6533c3..b927cfc64 100644 --- a/cmds/recv.c +++ b/cmds/recv.c @@ -81,23 +81,45 @@ int setup_client_socket(struct uftrace_opts *opts) .sin_family = AF_INET, .sin_port = htons(opts->port), }; - struct hostent *hostinfo; + struct addrinfo *results, hints; + int err; int sock; int one = 1; - sock = socket(AF_INET, SOCK_STREAM, 0); + // Since your original code is using sockaddr_in and AF_INET, + // use it as well. Use AF_UNSPEC above to allow getaddrinfo() + // to find both IPv4 and IPv6 addresses for the hostname: + // + // Just make sure the rest of your code is equally family- + // agnostic when dealing with the IP addresses associated + // with this connection. For instance, make sure any uses + // of sockaddr_in are changed to sockaddr_storage, + // and pay attention to its ai_ or ss_family field, etc. + // + // Next, we may loop over trying all addresses returned by getaddrinfo + // like in the example loops over the results list (accepted answer): + // IPv4 and IPv6 support is shown in answer 8 here: + // stackoverflow.com/questions/52727565/client-in-c-use-gethostbyname-or-getaddrinfo + + memset(&hints, 0, sizeof hints); + hints.ai_family = addr.sin_family; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + err = getaddrinfo(opts->host, NULL, &hints, &results); + if (err) + pr_err_ns("Failed to resolve host %s: %s\n", opts->host, gai_strerror(err)); + + addr.sin_addr = ((struct sockaddr_in *)results->ai_addr)->sin_addr; + freeaddrinfo(results); + + sock = socket(hints.ai_family, hints.ai_socktype, 0); if (sock < 0) pr_err("socket create failed"); if (setsockopt(sock, SOL_TCP, TCP_NODELAY, &one, sizeof(one)) != 0) pr_warn("socket setting failed\n"); - hostinfo = gethostbyname(opts->host); - if (hostinfo == NULL) - pr_err("cannot find host: %s", opts->host); - - addr.sin_addr = *(struct in_addr *)hostinfo->h_addr; - if (connect(sock, (const struct sockaddr *)&addr, sizeof(addr)) < 0) pr_err("socket connect failed (host: %s, port: %d)", opts->host, opts->port);