Skip to content

Commit

Permalink
cmd/recv.c: Migrate from deprecated gethostbyname() to getaddrinfo()
Browse files Browse the repository at this point in the history
The Fedora review-tool runs rpmlint on the binary packages and warned
that the uftrace tool was using gethostbyname. Switching to getaddrinfo
helps to get accepted, also for later uftrace distro packaging reviews:

POSIX.1-2008 removes the specifications of gethostbyname(), gethostbyaddr(),
and h_errno, recommending the use of getaddrinfo(3) and getnameinfo(3) instead:

They return a list of addrs or hostnames, are thread-safe and optionally
allow us to also use IPv6. This 1st step continues with IPv4 and only
still tries to connect to the primary, 1st address (for a small commit).

Signed-off-by: Bernhard Kaindl <contact@bernhard.kaindl.dev>
  • Loading branch information
Bernhard Kaindl authored and bernhardkaindl committed Mar 28, 2023
1 parent e472b33 commit ff1fc1c
Showing 1 changed file with 30 additions and 8 deletions.
38 changes: 30 additions & 8 deletions cmds/recv.c
Expand Up @@ -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);
/*
* Comment for the migration to use getaddrinfo()
* in order to not use the deprecated gethostbyname():
*
* Next, we may want to loop over trying all addresses returned
* by getaddrinfo(). (like in the example loops linked below)
*
* After this, the code could be made IPv4/IPv6-agnostic: For this,
* we'd change sockaddr_in to sockaddr_storage, check ai_family,
* and use AF_UNSPEC in place of AF_INET which will allow getaddrinfo()
* to return IPv4 and IPv6 addrs. (and the server would be updated too)
*
* A very nice example is shown in the accepted answer and 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);

Expand Down

0 comments on commit ff1fc1c

Please sign in to comment.