summary refs log tree commit diff
path: root/src/nm-helpers/nm-daemon-helper.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2025-12-13 13:48:57 +0100
committerMichael Biebl <biebl@debian.org>2025-12-13 13:48:57 +0100
commit6de29285e533f4fec22a219013f3687edb6b7399 (patch)
tree4b1627413f2e8fc8e3ccfa1496a79a04b8a71bde /src/nm-helpers/nm-daemon-helper.c
parent01609e485803fa250413385ae209660fb7b30a2e (diff)
New upstream version 1.54.3 upstream/1.54.3
Diffstat (limited to 'src/nm-helpers/nm-daemon-helper.c')
-rw-r--r--src/nm-helpers/nm-daemon-helper.c188
1 files changed, 188 insertions, 0 deletions
diff --git a/src/nm-helpers/nm-daemon-helper.c b/src/nm-helpers/nm-daemon-helper.c
new file mode 100644
index 00000000..759993a4
--- /dev/null
+++ b/src/nm-helpers/nm-daemon-helper.c
@@ -0,0 +1,188 @@
+/* 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;
+    nm_auto_free char *services = NULL;
+    union {
+        struct sockaddr_in  in;
+        struct sockaddr_in6 in6;
+    } sockaddr;
+    socklen_t sockaddr_size;
+    char      name[NI_MAXHOST];
+    char     *saveptr = NULL;
+    char     *service;
+    char     *str;
+    int       ret;
+
+    address = read_arg();
+    if (!address)
+        return RETURN_INVALID_ARGS;
+
+    services = read_arg();
+    if (!services) {
+        /* Called by an old NM version which doesn't support the 'services'
+         * argument. Use both services. */
+        services = strdup("dns,files");
+    }
+
+    memset(&sockaddr, 0, sizeof(sockaddr));
+
+    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;
+
+    for (str = services; (service = strtok_r(str, ",", &saveptr)); str = NULL) {
+        if (!NM_IN_STRSET(service, "dns", "files")) {
+            fprintf(stderr, "Unsupported resolver service '%s'\n", service);
+            continue;
+        }
+
+#if defined(__GLIBC__)
+        __nss_configure_lookup("hosts", service);
+#endif
+
+        ret = getnameinfo((struct sockaddr *) &sockaddr,
+                          sockaddr_size,
+                          name,
+                          sizeof(name),
+                          NULL,
+                          0,
+                          NI_NAMEREQD);
+
+        if (ret == 0) {
+            printf("%s", name);
+            return RETURN_SUCCESS;
+        } else if (ret == EAI_SYSTEM) {
+            char buf[1024];
+            int  errsv = errno;
+
+            fprintf(stderr,
+                    "getnameinfo() via service '%s' failed: %d (%s), system error: %d (%s)\n",
+                    service,
+                    ret,
+                    gai_strerror(ret),
+                    errsv,
+                    _nm_strerror_r(errsv, buf, sizeof(buf)));
+        } else {
+            fprintf(stderr,
+                    "getnameinfo() via service '%s' failed: %d (%s)\n",
+                    service,
+                    ret,
+                    gai_strerror(ret));
+        }
+#if !defined(__GLIBC__)
+        break;
+#endif
+    }
+
+    return RETURN_ERROR;
+}
+
+static int
+cmd_read_file_as_user(void)
+{
+    nm_auto_free char *user     = NULL;
+    nm_auto_free char *filename = NULL;
+    char               error[1024];
+
+    user = read_arg();
+    if (!user)
+        return RETURN_INVALID_ARGS;
+
+    filename = read_arg();
+    if (!filename)
+        return RETURN_INVALID_ARGS;
+
+    if (more_args())
+        return RETURN_INVALID_ARGS;
+
+    if (!nm_utils_set_effective_user(user, error, sizeof(error))) {
+        fprintf(stderr, "Failed to set effective user '%s': %s", user, error);
+        return RETURN_ERROR;
+    }
+
+    if (!nm_utils_read_file_to_stdout(filename, error, sizeof(error))) {
+        fprintf(stderr, "Failed to read file '%s' as user '%s': %s", filename, user, error);
+        return RETURN_ERROR;
+    }
+
+    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();
+    if (nm_streq(cmd, "read-file-as-user"))
+        return cmd_read_file_as_user();
+
+    return RETURN_INVALID_CMD;
+}