NetworkManager/src/nm-daemon-helper/nm-daemon-helper.c
Thomas Haller c42f6f0997 daemon-helper: use _nm_strerror_r() to avoid non-thread-safe strerror()
Yes, there probably are not multiple threads here. It's a matter of principle to
not use smelly functions.

Also, copy the "errno" value we want to print, before calling various functions.
2023-09-12 12:39:43 +00:00

132 lines
2.8 KiB
C

/* SPDX-License-Identifier: LGPL-2.1-or-later */
/* Copyright (C) 2021 Red Hat, Inc. */
#include "libnm-std-aux/nm-default-std.h"
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netdb.h>
#if defined(__GLIBC__)
#include <nss.h>
#endif
#include <stdarg.h>
enum {
RETURN_SUCCESS = 0,
RETURN_INVALID_CMD = 1,
RETURN_INVALID_ARGS = 2,
RETURN_ERROR = 3,
};
static char *
read_arg(void)
{
nm_auto_free char *arg = NULL;
size_t len = 0;
if (getdelim(&arg, &len, '\0', stdin) < 0)
return NULL;
return nm_steal_pointer(&arg);
}
static int
more_args(void)
{
nm_auto_free char *arg = NULL;
arg = read_arg();
return !!arg;
}
static int
cmd_version(void)
{
if (more_args())
return RETURN_INVALID_ARGS;
printf("1");
return RETURN_SUCCESS;
}
static int
cmd_resolve_address(void)
{
nm_auto_free char *address = NULL;
union {
struct sockaddr_in in;
struct sockaddr_in6 in6;
} sockaddr;
socklen_t sockaddr_size;
char name[NI_MAXHOST];
int ret;
address = read_arg();
if (!address)
return RETURN_INVALID_ARGS;
if (more_args())
return RETURN_INVALID_ARGS;
memset(&sockaddr, 0, sizeof(sockaddr));
#if defined(__GLIBC__)
__nss_configure_lookup("hosts", "dns");
#endif
if (inet_pton(AF_INET, address, &sockaddr.in.sin_addr) == 1) {
sockaddr.in.sin_family = AF_INET;
sockaddr_size = sizeof(struct sockaddr_in);
} else if (inet_pton(AF_INET6, address, &sockaddr.in6.sin6_addr) == 1) {
sockaddr.in6.sin6_family = AF_INET6;
sockaddr_size = sizeof(struct sockaddr_in6);
} else
return RETURN_INVALID_ARGS;
ret = getnameinfo((struct sockaddr *) &sockaddr,
sockaddr_size,
name,
sizeof(name),
NULL,
0,
NI_NAMEREQD);
if (ret != 0) {
if (ret == EAI_SYSTEM) {
int errsv = errno;
char buf[1024];
fprintf(stderr,
"getnameinfo() failed: %d (%s), system error: %d (%s)\n",
ret,
gai_strerror(ret),
errsv,
_nm_strerror_r(errsv, buf, sizeof(buf)));
} else {
fprintf(stderr, "getnameinfo() failed: %d (%s)\n", ret, gai_strerror(ret));
}
return RETURN_ERROR;
}
printf("%s", name);
return RETURN_SUCCESS;
}
int
main(int argc, char **argv)
{
nm_auto_free char *cmd = NULL;
cmd = read_arg();
if (!cmd)
return RETURN_INVALID_CMD;
if (nm_streq(cmd, "version"))
return cmd_version();
if (nm_streq(cmd, "resolve-address"))
return cmd_resolve_address();
return RETURN_INVALID_CMD;
}