]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #3481 from poettering/relative-memcg
authorLennart Poettering <lennart@poettering.net>
Thu, 16 Jun 2016 11:56:23 +0000 (13:56 +0200)
committerGitHub <noreply@github.com>
Thu, 16 Jun 2016 11:56:23 +0000 (13:56 +0200)
various changes, most importantly regarding memory metrics

34 files changed:
CODING_STYLE
coccinelle/htonl.cocci [new file with mode: 0644]
configure.ac
man/systemd.exec.xml
man/udevadm.xml
src/basic/formats-util.h
src/basic/process-util.c
src/basic/socket-util.c
src/core/execute.c
src/core/load-fragment.c
src/core/socket.c
src/libsystemd-network/arp-util.c
src/libsystemd-network/dhcp-network.c
src/libsystemd-network/lldp-network.c
src/libsystemd-network/sd-dhcp-server.c
src/libsystemd/sd-daemon/sd-daemon.c
src/libudev/libudev-monitor.c
src/network/networkd-ipv4ll.c
src/network/networkd-netdev-tunnel.c
src/nss-myhostname/nss-myhostname.c
src/resolve/resolve-tool.c
src/resolve/resolved-bus.c
src/resolve/resolved-dns-answer.c
src/resolve/resolved-dns-answer.h
src/resolve/resolved-dns-scope.c
src/resolve/resolved-dns-scope.h
src/resolve/resolved-dns-transaction.c
src/resolve/resolved-dns-zone.c
src/resolve/resolved-dns-zone.h
src/shared/install.c
src/test/test-nss.c
src/test/test-process-util.c
src/test/test-socket-util.c
src/udev/udevadm-info.c

index e762d42edb0249f1c2f2467f88fcc7c2079a685b..f31d76f8cef5a789f169bf53ec48b5e524ff87c8 100644 (file)
   least initially), but it needs to be there. This is particularly important
   for objects that unprivileged users may allocate, but also matters for
   everything else any user may allocated.
+
+- htonl()/ntohl() and htons()/ntohs() are weird. Please use htobe32() and
+  htobe16() instead, it's much more descriptive, and actually says what really
+  is happening, after all htonl() and htons() don't operation on longs and
+  shorts as their name would suggest, but on uint32_t and uint16_t. Also,
+  "network byte order" is just a weird name for "big endian", hence we might
+  want to call it "big endian" right-away.
diff --git a/coccinelle/htonl.cocci b/coccinelle/htonl.cocci
new file mode 100644 (file)
index 0000000..4e69bb7
--- /dev/null
@@ -0,0 +1,20 @@
+@@
+expression s;
+@@
+- htonl(s)
++ htobe32(s)
+@@
+expression s;
+@@
+- htons(s)
++ htobe16(s)
+@@
+expression s;
+@@
+- ntohl(s)
++ be32toh(s)
+@@
+expression s;
+@@
+- ntohs(s)
++ be16toh(s)
index ffc6eedcdd26b7383aa54d904d97845a210fc70d..7fd78bfb60641e75e6b0dca326277424df787723 100644 (file)
@@ -249,6 +249,7 @@ AC_CHECK_SIZEOF(uid_t)
 AC_CHECK_SIZEOF(gid_t)
 AC_CHECK_SIZEOF(time_t)
 AC_CHECK_SIZEOF(dev_t)
+AC_CHECK_SIZEOF(ino_t)
 AC_CHECK_SIZEOF(rlim_t,,[
        #include <sys/time.h>
        #include <sys/resource.h>
index a39e800854fe9cd919df7cfec5ce4dc4ff6b0deb..dbfc7692f78315604756aecf87527c1b5aaa79f9 100644 (file)
         <citerefentry project='man-pages'><refentrytitle>termcap</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
         </para></listitem>
       </varlistentry>
+
+      <varlistentry>
+        <term><varname>$JOURNAL_STREAM</varname></term>
+
+        <listitem><para>If the standard output or standard error output of the executed processes are connected to the
+        journal (for example, by setting <varname>StandardError=journal</varname>) <varname>$JOURNAL_STREAM</varname>
+        contains the device and inode numbers of the connection file descriptor, formatted in decimal, separated by a
+        colon (<literal>:</literal>). This permits invoked processes to safely detect whether their standard output or
+        standard error output are connected to the journal. The device and inode numbers of the file descriptors should
+        be compared with the values set in the environment variable to determine whether the process output is still
+        connected to the journal. Note that it is generally not sufficient to only check whether
+        <varname>$JOURNAL_STREAM</varname> is set at all as services might invoke external processes replacing their
+        standard output or standard error output, without unsetting the environment variable.</para>
+
+        <para>This environment variable is primarily useful to allow services to optionally upgrade their used log
+        protocol to the native journal protocol (using
+        <citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>3</manvolnum></citerefentry> and other
+        functions) if their standard output or standard error output is connected to the journal anyway, thus enabling
+        delivery of structured metadata along with logged messages.</para></listitem>
+      </varlistentry>
     </variablelist>
 
     <para>Additional variables may be configured by the following
index 8c1abd2770cfaaf12164d69a2bcf58ea9bcb0193..1c7921f5bdd853a0ba6bc78096825dc940bc06a4 100644 (file)
       <para>Modify the internal state of the running udev daemon.</para>
       <variablelist>
         <varlistentry>
-          <term><option>-x</option></term>
+          <term><option>-e</option></term>
           <term><option>--exit</option></term>
           <listitem>
             <para>Signal and wait for systemd-udevd to exit.</para>
index 9b4e8e98faacf301a125a092a2070861c75e0391..39a185f59b4affffedc8044b556a4ab019edcd95 100644 (file)
 #else
 #  error Unknown rlim_t size
 #endif
+
+#if SIZEOF_DEV_T == 8
+#  define DEV_FMT "%" PRIu64
+#elif SIZEOF_DEV_T == 4
+#  define DEV_FMT "%" PRIu32
+#else
+#  error Unknown dev_t size
+#endif
+
+#if SIZEOF_INO_T == 8
+#  define INO_FMT "%" PRIu64
+#elif SIZEOF_INO_T == 4
+#  define INO_FMT "%" PRIu32
+#else
+#  error Unknown ino_t size
+#endif
index 08fa98bb9e4871fc937385d0552f68d4c29e9d04..b5b068ad389d26e65d781b095431725c7b4a1c74 100644 (file)
@@ -110,6 +110,15 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
         assert(line);
         assert(pid >= 0);
 
+        /* Retrieves a process' command line. Replaces unprintable characters while doing so by whitespace (coalescing
+         * multiple sequential ones into one). If max_length is != 0 will return a string of the specified size at most
+         * (the trailing NUL byte does count towards the length here!), abbreviated with a "..." ellipsis. If
+         * comm_fallback is true and the process has no command line set (the case for kernel threads), or has a
+         * command line that resolves to the empty string will return the "comm" name of the process instead.
+         *
+         * Returns -ESRCH if the process doesn't exist, and -ENOENT if the process has no command line (and
+         * comm_fallback is false). */
+
         p = procfs_file_alloca(pid, "cmdline");
 
         f = fopen(p, "re");
@@ -119,12 +128,22 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
                 return -errno;
         }
 
-        if (max_length == 0) {
+        if (max_length == 1) {
+
+                /* If there's only room for one byte, return the empty string */
+                r = new0(char, 1);
+                if (!r)
+                        return -ENOMEM;
+
+                *line = r;
+                return 0;
+
+        } else if (max_length == 0) {
                 size_t len = 0, allocated = 0;
 
                 while ((c = getc(f)) != EOF) {
 
-                        if (!GREEDY_REALLOC(r, allocated, len+2)) {
+                        if (!GREEDY_REALLOC(r, allocated, len+3)) {
                                 free(r);
                                 return -ENOMEM;
                         }
@@ -136,7 +155,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
                                 }
 
                                 r[len++] = c;
-                        } else
+                        } else if (len > 0)
                                 space = true;
                }
 
@@ -144,6 +163,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
                         r[len] = 0;
 
         } else {
+                bool dotdotdot = false;
                 size_t left;
 
                 r = new(char, max_length);
@@ -155,28 +175,46 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
                 while ((c = getc(f)) != EOF) {
 
                         if (isprint(c)) {
+
                                 if (space) {
-                                        if (left <= 4)
+                                        if (left <= 2) {
+                                                dotdotdot = true;
                                                 break;
+                                        }
 
                                         *(k++) = ' ';
                                         left--;
                                         space = false;
                                 }
 
-                                if (left <= 4)
+                                if (left <= 1) {
+                                        dotdotdot = true;
                                         break;
+                                }
 
                                 *(k++) = (char) c;
                                 left--;
-                        }  else
+                        }  else if (k > r)
                                 space = true;
                 }
 
-                if (left <= 4) {
-                        size_t n = MIN(left-1, 3U);
-                        memcpy(k, "...", n);
-                        k[n] = 0;
+                if (dotdotdot) {
+                        if (max_length <= 4) {
+                                k = r;
+                                left = max_length;
+                        } else {
+                                k = r + max_length - 4;
+                                left = 4;
+
+                                /* Eat up final spaces */
+                                while (k > r && isspace(k[-1])) {
+                                        k--;
+                                        left++;
+                                }
+                        }
+
+                        strncpy(k, "...", left-1);
+                        k[left] = 0;
                 } else
                         *k = 0;
         }
@@ -195,7 +233,37 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
                 if (h < 0)
                         return h;
 
-                r = strjoin("[", t, "]", NULL);
+                if (max_length == 0)
+                        r = strjoin("[", t, "]", NULL);
+                else {
+                        size_t l;
+
+                        l = strlen(t);
+
+                        if (l + 3 <= max_length)
+                                r = strjoin("[", t, "]", NULL);
+                        else if (max_length <= 6) {
+
+                                r = new(char, max_length);
+                                if (!r)
+                                        return -ENOMEM;
+
+                                memcpy(r, "[...]", max_length-1);
+                                r[max_length-1] = 0;
+                        } else {
+                                char *e;
+
+                                t[max_length - 6] = 0;
+
+                                /* Chop off final spaces */
+                                e = strchr(t, 0);
+                                while (e > t && isspace(e[-1]))
+                                        e--;
+                                *e = 0;
+
+                                r = strjoin("[", t, "...]", NULL);
+                        }
+                }
                 if (!r)
                         return -ENOMEM;
         }
index c8769a54f4e089bd25f7c3dcc591d820d1e89d4c..385c3e4df337368045d5eed37b44c130de067fae 100644 (file)
@@ -85,7 +85,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
                         return -EINVAL;
 
                 a->sockaddr.in6.sin6_family = AF_INET6;
-                a->sockaddr.in6.sin6_port = htons((uint16_t) u);
+                a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
                 a->size = sizeof(struct sockaddr_in6);
 
         } else if (*s == '/') {
@@ -133,7 +133,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
                         if (r > 0) {
                                 /* Gotcha, it's a traditional IPv4 address */
                                 a->sockaddr.in.sin_family = AF_INET;
-                                a->sockaddr.in.sin_port = htons((uint16_t) u);
+                                a->sockaddr.in.sin_port = htobe16((uint16_t)u);
                                 a->size = sizeof(struct sockaddr_in);
                         } else {
                                 unsigned idx;
@@ -147,7 +147,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
                                         return -EINVAL;
 
                                 a->sockaddr.in6.sin6_family = AF_INET6;
-                                a->sockaddr.in6.sin6_port = htons((uint16_t) u);
+                                a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
                                 a->sockaddr.in6.sin6_scope_id = idx;
                                 a->sockaddr.in6.sin6_addr = in6addr_any;
                                 a->size = sizeof(struct sockaddr_in6);
@@ -164,12 +164,12 @@ int socket_address_parse(SocketAddress *a, const char *s) {
 
                         if (socket_ipv6_is_supported()) {
                                 a->sockaddr.in6.sin6_family = AF_INET6;
-                                a->sockaddr.in6.sin6_port = htons((uint16_t) u);
+                                a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
                                 a->sockaddr.in6.sin6_addr = in6addr_any;
                                 a->size = sizeof(struct sockaddr_in6);
                         } else {
                                 a->sockaddr.in.sin_family = AF_INET;
-                                a->sockaddr.in.sin_port = htons((uint16_t) u);
+                                a->sockaddr.in.sin_port = htobe16((uint16_t)u);
                                 a->sockaddr.in.sin_addr.s_addr = INADDR_ANY;
                                 a->size = sizeof(struct sockaddr_in);
                         }
@@ -488,9 +488,7 @@ int sockaddr_port(const struct sockaddr *_sa) {
         if (!IN_SET(sa->sa.sa_family, AF_INET, AF_INET6))
                 return -EAFNOSUPPORT;
 
-        return ntohs(sa->sa.sa_family == AF_INET6 ?
-                       sa->in6.sin6_port :
-                       sa->in.sin_port);
+        return be16toh(sa->sa.sa_family == AF_INET6 ? sa->in6.sin6_port : sa->in.sin_port);
 }
 
 int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret) {
@@ -506,13 +504,13 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
         case AF_INET: {
                 uint32_t a;
 
-                a = ntohl(sa->in.sin_addr.s_addr);
+                a = be32toh(sa->in.sin_addr.s_addr);
 
                 if (include_port)
                         r = asprintf(&p,
                                      "%u.%u.%u.%u:%u",
                                      a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
-                                     ntohs(sa->in.sin_port));
+                                     be16toh(sa->in.sin_port));
                 else
                         r = asprintf(&p,
                                      "%u.%u.%u.%u",
@@ -534,7 +532,7 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
                                 r = asprintf(&p,
                                              "%u.%u.%u.%u:%u",
                                              a[0], a[1], a[2], a[3],
-                                             ntohs(sa->in6.sin6_port));
+                                             be16toh(sa->in6.sin6_port));
                         else
                                 r = asprintf(&p,
                                              "%u.%u.%u.%u",
@@ -550,7 +548,7 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
                                 r = asprintf(&p,
                                              "[%s]:%u",
                                              a,
-                                             ntohs(sa->in6.sin6_port));
+                                             be16toh(sa->in6.sin6_port));
                                 if (r < 0)
                                         return -ENOMEM;
                         } else {
@@ -988,7 +986,7 @@ ssize_t next_datagram_size_fd(int fd) {
 
         l = recv(fd, NULL, 0, MSG_PEEK|MSG_TRUNC);
         if (l < 0) {
-                if (errno == EOPNOTSUPP)
+                if (errno == EOPNOTSUPP || errno == EFAULT)
                         goto fallback;
 
                 return -errno;
index c20650626c9563257b3c00648d5bea3507506885..3c3369373f54930f2ba97c7758e4532c6e577194 100644 (file)
@@ -289,7 +289,15 @@ static int connect_journal_socket(int fd, uid_t uid, gid_t gid) {
         return r;
 }
 
-static int connect_logger_as(const ExecContext *context, ExecOutput output, const char *ident, const char *unit_id, int nfd, uid_t uid, gid_t gid) {
+static int connect_logger_as(
+                const ExecContext *context,
+                ExecOutput output,
+                const char *ident,
+                const char *unit_id,
+                int nfd,
+                uid_t uid,
+                gid_t gid) {
+
         int fd, r;
 
         assert(context);
@@ -310,7 +318,7 @@ static int connect_logger_as(const ExecContext *context, ExecOutput output, cons
                 return -errno;
         }
 
-        fd_inc_sndbuf(fd, SNDBUF_SIZE);
+        (void) fd_inc_sndbuf(fd, SNDBUF_SIZE);
 
         dprintf(fd,
                 "%s\n"
@@ -328,11 +336,11 @@ static int connect_logger_as(const ExecContext *context, ExecOutput output, cons
                 output == EXEC_OUTPUT_KMSG || output == EXEC_OUTPUT_KMSG_AND_CONSOLE,
                 is_terminal_output(output));
 
-        if (fd != nfd) {
-                r = dup2(fd, nfd) < 0 ? -errno : nfd;
-                safe_close(fd);
-        } else
-                r = nfd;
+        if (fd == nfd)
+                return nfd;
+
+        r = dup2(fd, nfd) < 0 ? -errno : nfd;
+        safe_close(fd);
 
         return r;
 }
@@ -446,7 +454,10 @@ static int setup_output(
                 int fileno,
                 int socket_fd,
                 const char *ident,
-                uid_t uid, gid_t gid) {
+                uid_t uid,
+                gid_t gid,
+                dev_t *journal_stream_dev,
+                ino_t *journal_stream_ino) {
 
         ExecOutput o;
         ExecInput i;
@@ -456,6 +467,8 @@ static int setup_output(
         assert(context);
         assert(params);
         assert(ident);
+        assert(journal_stream_dev);
+        assert(journal_stream_ino);
 
         if (fileno == STDOUT_FILENO && params->stdout_fd >= 0) {
 
@@ -535,6 +548,17 @@ static int setup_output(
                 if (r < 0) {
                         log_unit_error_errno(unit, r, "Failed to connect %s to the journal socket, ignoring: %m", fileno == STDOUT_FILENO ? "stdout" : "stderr");
                         r = open_null_as(O_WRONLY, fileno);
+                } else {
+                        struct stat st;
+
+                        /* If we connected this fd to the journal via a stream, patch the device/inode into the passed
+                         * parameters, but only then. This is useful so that we can set $JOURNAL_STREAM that permits
+                         * services to detect whether they are connected to the journal or not. */
+
+                        if (fstat(fileno, &st) >= 0) {
+                                *journal_stream_dev = st.st_dev;
+                                *journal_stream_ino = st.st_ino;
+                        }
                 }
                 return r;
 
@@ -1278,6 +1302,8 @@ static int build_environment(
                 const char *home,
                 const char *username,
                 const char *shell,
+                dev_t journal_stream_dev,
+                ino_t journal_stream_ino,
                 char ***ret) {
 
         _cleanup_strv_free_ char **our_env = NULL;
@@ -1287,7 +1313,7 @@ static int build_environment(
         assert(c);
         assert(ret);
 
-        our_env = new0(char*, 11);
+        our_env = new0(char*, 12);
         if (!our_env)
                 return -ENOMEM;
 
@@ -1359,8 +1385,15 @@ static int build_environment(
                 our_env[n_env++] = x;
         }
 
+        if (journal_stream_dev != 0 && journal_stream_ino != 0) {
+                if (asprintf(&x, "JOURNAL_STREAM=" DEV_FMT ":" INO_FMT, journal_stream_dev, journal_stream_ino) < 0)
+                        return -ENOMEM;
+
+                our_env[n_env++] = x;
+        }
+
         our_env[n_env++] = NULL;
-        assert(n_env <= 11);
+        assert(n_env <= 12);
 
         *ret = our_env;
         our_env = NULL;
@@ -1473,10 +1506,12 @@ static int exec_child(
         _cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **accum_env = NULL, **final_argv = NULL;
         _cleanup_free_ char *mac_selinux_context_net = NULL;
         const char *username = NULL, *home = NULL, *shell = NULL, *wd;
+        dev_t journal_stream_dev = 0;
+        ino_t journal_stream_ino = 0;
+        bool needs_mount_namespace;
         uid_t uid = UID_INVALID;
         gid_t gid = GID_INVALID;
         int i, r;
-        bool needs_mount_namespace;
 
         assert(unit);
         assert(command);
@@ -1576,13 +1611,13 @@ static int exec_child(
                 return r;
         }
 
-        r = setup_output(unit, context, params, STDOUT_FILENO, socket_fd, basename(command->path), uid, gid);
+        r = setup_output(unit, context, params, STDOUT_FILENO, socket_fd, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino);
         if (r < 0) {
                 *exit_status = EXIT_STDOUT;
                 return r;
         }
 
-        r = setup_output(unit, context, params, STDERR_FILENO, socket_fd, basename(command->path), uid, gid);
+        r = setup_output(unit, context, params, STDERR_FILENO, socket_fd, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino);
         if (r < 0) {
                 *exit_status = EXIT_STDERR;
                 return r;
@@ -1721,7 +1756,16 @@ static int exec_child(
                 }
         }
 
-        r = build_environment(context, params, n_fds, home, username, shell, &our_env);
+        r = build_environment(
+                        context,
+                        params,
+                        n_fds,
+                        home,
+                        username,
+                        shell,
+                        journal_stream_dev,
+                        journal_stream_ino,
+                        &our_env);
         if (r < 0) {
                 *exit_status = EXIT_MEMORY;
                 return r;
index 58d7275a96eb68119537c07aee44476af7c99ecb..8295cf45a621bb0587cdea552b572b161485f709 100644 (file)
@@ -3835,7 +3835,15 @@ static int load_from_path(Unit *u, const char *path) {
                         if (r >= 0)
                                 break;
                         filename = mfree(filename);
-                        if (r != -ENOENT)
+
+                        /* ENOENT means that the file is missing or is a dangling symlink.
+                         * ENOTDIR means that one of paths we expect to be is a directory
+                         * is not a directory, we should just ignore that.
+                         * EACCES means that the directory or file permissions are wrong.
+                         */
+                        if (r == -EACCES)
+                                log_debug_errno(r, "Cannot access \"%s\": %m", filename);
+                        else if (!IN_SET(r, -ENOENT, -ENOTDIR))
                                 return r;
 
                         /* Empty the symlink names for the next run */
index f6204d04bfd80f52935c2a9fa333ffae617e9ac5..e0980558851383220d2cfebc525c0fe20026cd36 100644 (file)
@@ -730,16 +730,16 @@ static int instance_from_socket(int fd, unsigned nr, char **instance) {
 
         case AF_INET: {
                 uint32_t
-                        a = ntohl(local.in.sin_addr.s_addr),
-                        b = ntohl(remote.in.sin_addr.s_addr);
+                        a = be32toh(local.in.sin_addr.s_addr),
+                        b = be32toh(remote.in.sin_addr.s_addr);
 
                 if (asprintf(&r,
                              "%u-%u.%u.%u.%u:%u-%u.%u.%u.%u:%u",
                              nr,
                              a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
-                             ntohs(local.in.sin_port),
+                             be16toh(local.in.sin_port),
                              b >> 24, (b >> 16) & 0xFF, (b >> 8) & 0xFF, b & 0xFF,
-                             ntohs(remote.in.sin_port)) < 0)
+                             be16toh(remote.in.sin_port)) < 0)
                         return -ENOMEM;
 
                 break;
@@ -760,9 +760,9 @@ static int instance_from_socket(int fd, unsigned nr, char **instance) {
                                      "%u-%u.%u.%u.%u:%u-%u.%u.%u.%u:%u",
                                      nr,
                                      a[0], a[1], a[2], a[3],
-                                     ntohs(local.in6.sin6_port),
+                                     be16toh(local.in6.sin6_port),
                                      b[0], b[1], b[2], b[3],
-                                     ntohs(remote.in6.sin6_port)) < 0)
+                                     be16toh(remote.in6.sin6_port)) < 0)
                                 return -ENOMEM;
                 } else {
                         char a[INET6_ADDRSTRLEN], b[INET6_ADDRSTRLEN];
@@ -771,9 +771,9 @@ static int instance_from_socket(int fd, unsigned nr, char **instance) {
                                      "%u-%s:%u-%s:%u",
                                      nr,
                                      inet_ntop(AF_INET6, &local.in6.sin6_addr, a, sizeof(a)),
-                                     ntohs(local.in6.sin6_port),
+                                     be16toh(local.in6.sin6_port),
                                      inet_ntop(AF_INET6, &remote.in6.sin6_addr, b, sizeof(b)),
-                                     ntohs(remote.in6.sin6_port)) < 0)
+                                     be16toh(remote.in6.sin6_port)) < 0)
                                 return -ENOMEM;
                 }
 
index 4660c7ea096eeb47c2c0576e9e762879970e5019..02028bf28afb7a844909c8bd17eae5147abdbb4e 100644 (file)
@@ -79,7 +79,7 @@ int arp_network_bind_raw_socket(int ifindex, be32_t address, const struct ether_
         };
         union sockaddr_union link = {
                 .ll.sll_family = AF_PACKET,
-                .ll.sll_protocol = htons(ETH_P_ARP),
+                .ll.sll_protocol = htobe16(ETH_P_ARP),
                 .ll.sll_ifindex = ifindex,
                 .ll.sll_halen = ETH_ALEN,
                 .ll.sll_addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
@@ -112,17 +112,17 @@ static int arp_send_packet(int fd, int ifindex,
                            bool announce) {
         union sockaddr_union link = {
                 .ll.sll_family = AF_PACKET,
-                .ll.sll_protocol = htons(ETH_P_ARP),
+                .ll.sll_protocol = htobe16(ETH_P_ARP),
                 .ll.sll_ifindex = ifindex,
                 .ll.sll_halen = ETH_ALEN,
                 .ll.sll_addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
         };
         struct ether_arp arp = {
-                .ea_hdr.ar_hrd = htons(ARPHRD_ETHER), /* HTYPE */
-                .ea_hdr.ar_pro = htons(ETHERTYPE_IP), /* PTYPE */
+                .ea_hdr.ar_hrd = htobe16(ARPHRD_ETHER), /* HTYPE */
+                .ea_hdr.ar_pro = htobe16(ETHERTYPE_IP), /* PTYPE */
                 .ea_hdr.ar_hln = ETH_ALEN, /* HLEN */
                 .ea_hdr.ar_pln = sizeof(be32_t), /* PLEN */
-                .ea_hdr.ar_op = htons(ARPOP_REQUEST), /* REQUEST */
+                .ea_hdr.ar_op = htobe16(ARPOP_REQUEST), /* REQUEST */
         };
         int r;
 
index fac25e0fa2e059047cdb54c17ba2a99862ea7d14..a9f5a0a5de01973e560518ab277106949f0494f6 100644 (file)
@@ -107,9 +107,9 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
                 return -errno;
 
         link->ll.sll_family = AF_PACKET;
-        link->ll.sll_protocol = htons(ETH_P_IP);
+        link->ll.sll_protocol = htobe16(ETH_P_IP);
         link->ll.sll_ifindex = ifindex;
-        link->ll.sll_hatype = htons(arp_type);
+        link->ll.sll_hatype = htobe16(arp_type);
         link->ll.sll_halen = mac_addr_len;
         memcpy(link->ll.sll_addr, bcast_addr, mac_addr_len);
 
index f031760351f95fcf3e14b2c8c3d6a3d29252acc4..59c25598e944f8beba4d0c8197e8783d7d6f986c 100644 (file)
@@ -57,7 +57,8 @@ int lldp_network_bind_raw_socket(int ifindex) {
 
         assert(ifindex > 0);
 
-        fd = socket(PF_PACKET, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, htons(ETHERTYPE_LLDP));
+        fd = socket(PF_PACKET, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK,
+                    htobe16(ETHERTYPE_LLDP));
         if (fd < 0)
                 return -errno;
 
index ea4f03df1d5fe881e496ddd3433f4ef5ca34fde0..11ee2e252ed1e878371ff2a54912d91a35c2bbd8 100644 (file)
@@ -260,7 +260,7 @@ static int dhcp_server_send_unicast_raw(sd_dhcp_server *server,
                                         DHCPPacket *packet, size_t len) {
         union sockaddr_union link = {
                 .ll.sll_family = AF_PACKET,
-                .ll.sll_protocol = htons(ETH_P_IP),
+                .ll.sll_protocol = htobe16(ETH_P_IP),
                 .ll.sll_ifindex = server->ifindex,
                 .ll.sll_halen = ETH_ALEN,
         };
index 4da9dbfd63f894e1c02cf37954c847721764d6a5..b20a7ebb4c3c8b6be14aaec2cfe85ccb1886e8e7 100644 (file)
@@ -310,12 +310,12 @@ _public_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint
                         if (l < sizeof(struct sockaddr_in))
                                 return -EINVAL;
 
-                        return htons(port) == sockaddr.in.sin_port;
+                        return htobe16(port) == sockaddr.in.sin_port;
                 } else {
                         if (l < sizeof(struct sockaddr_in6))
                                 return -EINVAL;
 
-                        return htons(port) == sockaddr.in6.sin6_port;
+                        return htobe16(port) == sockaddr.in6.sin6_port;
                 }
         }
 
index f870eba9eb2715a24d0e47986d7d095cc8f3d873..1f9d16c45084ff91bf3e129e69172f8a3b684390 100644 (file)
@@ -650,9 +650,9 @@ retry:
 
         if (memcmp(buf.raw, "libudev", 8) == 0) {
                 /* udev message needs proper version magic */
-                if (buf.nlh.magic != htonl(UDEV_MONITOR_MAGIC)) {
+                if (buf.nlh.magic != htobe32(UDEV_MONITOR_MAGIC)) {
                         log_debug("unrecognized message signature (%x != %x)",
-                                 buf.nlh.magic, htonl(UDEV_MONITOR_MAGIC));
+                                 buf.nlh.magic, htobe32(UDEV_MONITOR_MAGIC));
                         return NULL;
                 }
                 if (buf.nlh.properties_off+32 > (size_t)buflen) {
@@ -715,7 +715,7 @@ int udev_monitor_send_device(struct udev_monitor *udev_monitor,
         ssize_t blen, count;
         struct udev_monitor_netlink_header nlh = {
                 .prefix = "libudev",
-                .magic = htonl(UDEV_MONITOR_MAGIC),
+                .magic = htobe32(UDEV_MONITOR_MAGIC),
                 .header_size = sizeof nlh,
         };
         struct iovec iov[2] = {
@@ -736,19 +736,19 @@ int udev_monitor_send_device(struct udev_monitor *udev_monitor,
 
         /* fill in versioned header */
         val = udev_device_get_subsystem(udev_device);
-        nlh.filter_subsystem_hash = htonl(util_string_hash32(val));
+        nlh.filter_subsystem_hash = htobe32(util_string_hash32(val));
 
         val = udev_device_get_devtype(udev_device);
         if (val != NULL)
-                nlh.filter_devtype_hash = htonl(util_string_hash32(val));
+                nlh.filter_devtype_hash = htobe32(util_string_hash32(val));
 
         /* add tag bloom filter */
         tag_bloom_bits = 0;
         udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(udev_device))
                 tag_bloom_bits |= util_string_bloom64(udev_list_entry_get_name(list_entry));
         if (tag_bloom_bits > 0) {
-                nlh.filter_tag_bloom_hi = htonl(tag_bloom_bits >> 32);
-                nlh.filter_tag_bloom_lo = htonl(tag_bloom_bits & 0xffffffff);
+                nlh.filter_tag_bloom_hi = htobe32(tag_bloom_bits >> 32);
+                nlh.filter_tag_bloom_lo = htobe32(tag_bloom_bits & 0xffffffff);
         }
 
         /* add properties list */
index 735c231a4c4748d6da734ecbdf46c5436885dfb9..2d81311e8117b5dc848b6f919e3051b99be7a6cc 100644 (file)
@@ -138,7 +138,7 @@ static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
         ll_addr->family = AF_INET;
         ll_addr->in_addr.in = address;
         ll_addr->prefixlen = 16;
-        ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htonl(0xfffffffflu >> ll_addr->prefixlen);
+        ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htobe32(0xfffffffflu >> ll_addr->prefixlen);
         ll_addr->scope = RT_SCOPE_LINK;
 
         r = address_configure(ll_addr, link, ipv4ll_address_handler, false);
index 58dec36c9adbc19b61ad0aab90a6bd5861f199e9..77a4734df861fdd807eea5dd4eed22170b428693 100644 (file)
@@ -35,7 +35,7 @@
 #include "util.h"
 
 #define DEFAULT_TNL_HOP_LIMIT   64
-#define IP6_FLOWINFO_FLOWLABEL  htonl(0x000FFFFF)
+#define IP6_FLOWINFO_FLOWLABEL  htobe32(0x000FFFFF)
 
 static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = {
         [NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6",
@@ -519,7 +519,7 @@ int config_parse_ipv6_flowlabel(const char* unit,
                 if (k > 0xFFFFF)
                         log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPv6 flowlabel option, ignoring: %s", rvalue);
                 else {
-                        *ipv6_flowlabel = htonl(k) & IP6_FLOWINFO_FLOWLABEL;
+                        *ipv6_flowlabel = htobe32(k) & IP6_FLOWINFO_FLOWLABEL;
                         t->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL;
                 }
         }
index 2b83d127b7ac228366dc7f3f2dddd7baa3d53da6..9a6e157e123a3ac4ff7d9202c54f43b7df2ad971 100644 (file)
@@ -38,7 +38,7 @@
  * IPv6 we use ::1 which unfortunately will not translate back to the
  * hostname but instead something like "localhost" or so. */
 
-#define LOCALADDRESS_IPV4 (htonl(0x7F000002))
+#define LOCALADDRESS_IPV4 (htobe32(0x7F000002))
 #define LOCALADDRESS_IPV6 &in6addr_loopback
 
 NSS_GETHOSTBYNAME_PROTOTYPES(myhostname);
@@ -75,7 +75,7 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
                  * is optional */
 
                 canonical = "localhost";
-                local_address_ipv4 = htonl(INADDR_LOOPBACK);
+                local_address_ipv4 = htobe32(INADDR_LOOPBACK);
 
         } else if (is_gateway_hostname(name)) {
 
@@ -348,7 +348,7 @@ enum nss_status _nss_myhostname_gethostbyname3_r(
 
         if (is_localhost(name)) {
                 canonical = "localhost";
-                local_address_ipv4 = htonl(INADDR_LOOPBACK);
+                local_address_ipv4 = htobe32(INADDR_LOOPBACK);
 
         } else if (is_gateway_hostname(name)) {
 
@@ -437,9 +437,9 @@ enum nss_status _nss_myhostname_gethostbyaddr2_r(
                 if ((*(uint32_t*) addr) == LOCALADDRESS_IPV4)
                         goto found;
 
-                if ((*(uint32_t*) addr) == htonl(INADDR_LOOPBACK)) {
+                if ((*(uint32_t*) addr) == htobe32(INADDR_LOOPBACK)) {
                         canonical = "localhost";
-                        local_address_ipv4 = htonl(INADDR_LOOPBACK);
+                        local_address_ipv4 = htobe32(INADDR_LOOPBACK);
                         goto found;
                 }
 
index bc6dcf04a41e91b713cdd0c861b8dbde0ee272f8..2cb2e42b23b01185bee2b700dec2ae5a53eab48a 100644 (file)
@@ -199,7 +199,7 @@ static int resolve_host(sd_bus *bus, const char *name) {
                 if (ifindex > 0 && !if_indextoname(ifindex, ifname))
                         log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
 
-                r = in_addr_to_string(family, a, &pretty);
+                r = in_addr_ifindex_to_string(family, a, ifindex, &pretty);
                 if (r < 0)
                         return log_error_errno(r, "Failed to print address for %s: %m", name);
 
@@ -253,7 +253,7 @@ static int resolve_address(sd_bus *bus, int family, const union in_addr_union *a
         if (ifindex <= 0)
                 ifindex = arg_ifindex;
 
-        r = in_addr_to_string(family, address, &pretty);
+        r = in_addr_ifindex_to_string(family, address, ifindex, &pretty);
         if (r < 0)
                 return log_oom();
 
@@ -345,31 +345,6 @@ static int resolve_address(sd_bus *bus, int family, const union in_addr_union *a
         return 0;
 }
 
-static int parse_address(const char *s, int *family, union in_addr_union *address, int *ifindex) {
-        const char *percent, *a;
-        int ifi = 0;
-        int r;
-
-        percent = strchr(s, '%');
-        if (percent) {
-                if (parse_ifindex(percent+1, &ifi) < 0) {
-                        ifi = if_nametoindex(percent+1);
-                        if (ifi <= 0)
-                                return -EINVAL;
-                }
-
-                a = strndupa(s, percent - s);
-        } else
-                a = s;
-
-        r = in_addr_from_string_auto(a, family, address);
-        if (r < 0)
-                return r;
-
-        *ifindex = ifi;
-        return 0;
-}
-
 static int output_rr_packet(const void *d, size_t l, int ifindex) {
         _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
@@ -1392,7 +1367,7 @@ int main(int argc, char **argv) {
                         if (startswith(argv[optind], "dns:"))
                                 k = resolve_rfc4501(bus, argv[optind]);
                         else {
-                                k = parse_address(argv[optind], &family, &a, &ifindex);
+                                k = in_addr_ifindex_from_string_auto(argv[optind], &family, &a, &ifindex);
                                 if (k >= 0)
                                         k = resolve_address(bus, family, &a, ifindex);
                                 else
index 6d86cbf123e25d1ee6a0da78a61a218dd7baf2f9..f08c6c0637f52c6aad743ed2838f4762a964b25d 100644 (file)
@@ -245,17 +245,22 @@ static int parse_as_address(sd_bus_message *m, int ifindex, const char *hostname
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_free_ char *canonical = NULL;
         union in_addr_union parsed;
-        int r, ff;
+        int r, ff, parsed_ifindex = 0;
 
         /* Check if the hostname is actually already an IP address formatted as string. In that case just parse it,
          * let's not attempt to look it up. */
 
-        r = in_addr_from_string_auto(hostname, &ff, &parsed);
+        r = in_addr_ifindex_from_string_auto(hostname, &ff, &parsed, &parsed_ifindex);
         if (r < 0) /* not an address */
                 return 0;
 
         if (family != AF_UNSPEC && ff != family)
                 return sd_bus_reply_method_errorf(m, BUS_ERROR_NO_SUCH_RR, "The specified address is not of the requested family.");
+        if (ifindex > 0 && parsed_ifindex > 0 && parsed_ifindex != ifindex)
+                return sd_bus_reply_method_errorf(m, BUS_ERROR_NO_SUCH_RR, "The specified address interface index does not match requested interface.");
+
+        if (parsed_ifindex > 0)
+                ifindex = parsed_ifindex;
 
         r = sd_bus_message_new_method_return(m, &reply);
         if (r < 0)
@@ -288,7 +293,7 @@ static int parse_as_address(sd_bus_message *m, int ifindex, const char *hostname
         /* When an IP address is specified we just return it as canonical name, in order to avoid a DNS
          * look-up. However, we reformat it to make sure it's in a truly canonical form (i.e. on IPv6 the inner
          * omissions are always done the same way). */
-        r = in_addr_to_string(ff, &parsed, &canonical);
+        r = in_addr_ifindex_to_string(ff, &parsed, ifindex, &canonical);
         if (r < 0)
                 return r;
 
index 0dadf8b1dd14a6e2a384870aebeea4a66a0f9cbc..13dcba8421b5c90651331e3fdcdcbc128dd3d36a 100644 (file)
@@ -185,7 +185,7 @@ int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, Dns
         return dns_answer_add(*a, rr, ifindex, flags);
 }
 
-int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl) {
+int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl, int ifindex) {
         _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *soa = NULL;
 
         soa = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_SOA, name);
@@ -208,7 +208,7 @@ int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl) {
         soa->soa.expire = 1;
         soa->soa.minimum = ttl;
 
-        return dns_answer_add(a, soa, 0, DNS_ANSWER_AUTHENTICATED);
+        return dns_answer_add(a, soa, ifindex, DNS_ANSWER_AUTHENTICATED);
 }
 
 int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags) {
index 0679c610f5f210c775b464d1508b4dbcbc5b03f3..b2b86d17720fc6364293144765a45773d7d20b17 100644 (file)
@@ -56,7 +56,7 @@ DnsAnswer *dns_answer_unref(DnsAnswer *a);
 
 int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags);
 int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags);
-int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl);
+int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl, int ifindex);
 
 int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *combined_flags);
 int dns_answer_contains_rr(DnsAnswer *a, DnsResourceRecord *rr, DnsAnswerFlags *combined_flags);
index 6a69d7b7c2ebde485e0d5c25ca4d3978b79312ae..9d484d0a48cda54284567da0631757f3f2b2a25a 100644 (file)
@@ -721,7 +721,7 @@ void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
         assert(p->question->n_keys == 1);
         key = p->question->keys[0];
 
-        r = dns_zone_lookup(&s->zone, key, &answer, &soa, &tentative);
+        r = dns_zone_lookup(&s->zone, key, 0, &answer, &soa, &tentative);
         if (r < 0) {
                 log_debug_errno(r, "Failed to lookup key: %m");
                 return;
@@ -1029,3 +1029,12 @@ bool dns_scope_network_good(DnsScope *s) {
 
         return manager_routable(s->manager, AF_UNSPEC);
 }
+
+int dns_scope_ifindex(DnsScope *s) {
+        assert(s);
+
+        if (s->link)
+                return s->link->ifindex;
+
+        return 0;
+}
index 291e5817d081ce7df53c023f7376ac0ec1c09327..538bc61f8141db5a64b0f55b52619bb06964a247 100644 (file)
@@ -107,3 +107,5 @@ DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s);
 bool dns_scope_name_needs_search_domain(DnsScope *s, const char *name);
 
 bool dns_scope_network_good(DnsScope *s);
+
+int dns_scope_ifindex(DnsScope *s);
index a4a67623e7438bc0bdb5b6094db147d8ac429eaf..ed18df35cbe1333756685f49ac2dd650b2b9a2e8 100644 (file)
@@ -557,8 +557,7 @@ static int dns_transaction_open_tcp(DnsTransaction *t) {
         /* The interface index is difficult to determine if we are
          * connecting to the local host, hence fill this in right away
          * instead of determining it from the socket */
-        if (t->scope->link)
-                t->stream->ifindex = t->scope->link->ifindex;
+        t->stream->ifindex = dns_scope_ifindex(t->scope);
 
         dns_transaction_reset_answer(t);
 
@@ -798,12 +797,9 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
         switch (t->scope->protocol) {
 
         case DNS_PROTOCOL_LLMNR:
-                assert(t->scope->link);
+                /* For LLMNR we will not accept any packets from other interfaces */
 
-                /* For LLMNR we will not accept any packets from other
-                 * interfaces */
-
-                if (p->ifindex != t->scope->link->ifindex)
+                if (p->ifindex != dns_scope_ifindex(t->scope))
                         return;
 
                 if (p->family != t->scope->family)
@@ -820,10 +816,9 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
                 break;
 
         case DNS_PROTOCOL_MDNS:
-                assert(t->scope->link);
-
                 /* For mDNS we will not accept any packets from other interfaces */
-                if (p->ifindex != t->scope->link->ifindex)
+
+                if (p->ifindex != dns_scope_ifindex(t->scope))
                         return;
 
                 if (p->family != t->scope->family)
@@ -1246,7 +1241,7 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
          * for probing or verifying a zone item. */
         if (set_isempty(t->notify_zone_items)) {
 
-                r = dns_zone_lookup(&t->scope->zone, t->key, &t->answer, NULL, NULL);
+                r = dns_zone_lookup(&t->scope->zone, t->key, dns_scope_ifindex(t->scope), &t->answer, NULL, NULL);
                 if (r < 0)
                         return r;
                 if (r > 0) {
index 850eed8cb8414f6b5a8b03f58ab9358031f1f8ff..746a979f47d1d6c0f125735a04b8a5c1e3621ff0 100644 (file)
@@ -287,13 +287,16 @@ int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe) {
         return 0;
 }
 
-int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **ret_answer, DnsAnswer **ret_soa, bool *ret_tentative) {
+int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, int ifindex, DnsAnswer **ret_answer, DnsAnswer **ret_soa, bool *ret_tentative) {
         _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
         unsigned n_answer = 0;
         DnsZoneItem *j, *first;
         bool tentative = true, need_soa = false;
         int r;
 
+        /* Note that we don't actually need the ifindex for anything. However when it is passed we'll initialize the
+         * ifindex field in the answer with it */
+
         assert(z);
         assert(key);
         assert(ret_answer);
@@ -389,7 +392,7 @@ int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **ret_answer, Dns
                         if (k < 0)
                                 return k;
                         if (k > 0) {
-                                r = dns_answer_add(answer, j->rr, 0, DNS_ANSWER_AUTHENTICATED);
+                                r = dns_answer_add(answer, j->rr, ifindex, DNS_ANSWER_AUTHENTICATED);
                                 if (r < 0)
                                         return r;
 
@@ -398,7 +401,7 @@ int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **ret_answer, Dns
                 }
 
                 if (found && !added) {
-                        r = dns_answer_add_soa(soa, dns_resource_key_name(key), LLMNR_DEFAULT_TTL);
+                        r = dns_answer_add_soa(soa, dns_resource_key_name(key), LLMNR_DEFAULT_TTL, ifindex);
                         if (r < 0)
                                 return r;
                 }
@@ -415,7 +418,7 @@ int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **ret_answer, Dns
                         if (j->state != DNS_ZONE_ITEM_PROBING)
                                 tentative = false;
 
-                        r = dns_answer_add(answer, j->rr, 0, DNS_ANSWER_AUTHENTICATED);
+                        r = dns_answer_add(answer, j->rr, ifindex, DNS_ANSWER_AUTHENTICATED);
                         if (r < 0)
                                 return r;
                 }
@@ -435,7 +438,7 @@ int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **ret_answer, Dns
                         }
 
                         if (add_soa) {
-                                r = dns_answer_add_soa(soa, dns_resource_key_name(key), LLMNR_DEFAULT_TTL);
+                                r = dns_answer_add_soa(soa, dns_resource_key_name(key), LLMNR_DEFAULT_TTL, ifindex);
                                 if (r < 0)
                                         return r;
                         }
index 408833c359a8a16ba63f6aa999931bacf70d5481..a41df37e6b4340276b528d4584b7d88942ac7979 100644 (file)
@@ -65,7 +65,7 @@ void dns_zone_flush(DnsZone *z);
 int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe);
 void dns_zone_remove_rr(DnsZone *z, DnsResourceRecord *rr);
 
-int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **answer, DnsAnswer **soa, bool *tentative);
+int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, int ifindex, DnsAnswer **answer, DnsAnswer **soa, bool *tentative);
 
 void dns_zone_item_conflict(DnsZoneItem *i);
 void dns_zone_item_notify(DnsZoneItem *i);
index 64d66a45d38613567e6d03b672918d6f34c791ca..23cab96c5045f549949e6a66d96d8b4384f12aad 100644 (file)
@@ -779,7 +779,7 @@ static int find_symlinks(
 
         fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
         if (fd < 0) {
-                if (errno == ENOENT)
+                if (IN_SET(errno, ENOENT, ENOTDIR, EACCES))
                         return 0;
                 return -errno;
         }
@@ -1271,7 +1271,7 @@ static int unit_file_search(
                         info->path = path;
                         path = NULL;
                         return r;
-                } else if (r != -ENOENT)
+                } else if (!IN_SET(r, -ENOENT, -ENOTDIR, -EACCES))
                         return r;
         }
 
@@ -1296,7 +1296,7 @@ static int unit_file_search(
                                 info->path = path;
                                 path = NULL;
                                 return r;
-                        } else if (r != -ENOENT)
+                        } else if (!IN_SET(r, -ENOENT, -ENOTDIR, -EACCES))
                                 return r;
                 }
         }
@@ -2870,6 +2870,10 @@ int unit_file_get_list(
                 if (!d) {
                         if (errno == ENOENT)
                                 continue;
+                        if (IN_SET(errno, ENOTDIR, EACCES)) {
+                                log_debug("Failed to open \"%s\": %m", *i);
+                                continue;
+                        }
 
                         return -errno;
                 }
index 55af5922873ac08a408bba8ff215cb6ee983ed4a..c43bda591736845473387229946c84375d3e0213 100644 (file)
@@ -400,8 +400,8 @@ int main(int argc, char **argv) {
         _cleanup_free_ char *dir = NULL, *hostname = NULL;
         const char *module;
 
-        const uint32_t local_address_ipv4 = htonl(0x7F000001);
-        const uint32_t local_address_ipv4_2 = htonl(0x7F000002);
+        const uint32_t local_address_ipv4 = htobe32(0x7F000001);
+        const uint32_t local_address_ipv4_2 = htobe32(0x7F000002);
         _cleanup_free_ struct local_address *addresses = NULL;
         int n_addresses;
 
index 8bb5f6e3a31b396dfcaefc8bbdfbf493d0012719..af2c9282d47e67ef5127d8a54cff9a95c7f01faf 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <sched.h>
+#include <sys/mount.h>
 #include <sys/personality.h>
+#include <sys/prctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -26,6 +29,7 @@
 
 #include "alloc-util.h"
 #include "architecture.h"
+#include "fd-util.h"
 #include "log.h"
 #include "macro.h"
 #include "parse-util.h"
@@ -59,7 +63,11 @@ static void test_get_process_comm(pid_t pid) {
         log_info("PID"PID_FMT" cmdline: '%s'", pid, c);
 
         assert_se(get_process_cmdline(pid, 8, false, &d) >= 0);
-        log_info("PID"PID_FMT" cmdline truncated: '%s'", pid, d);
+        log_info("PID"PID_FMT" cmdline truncated to 8: '%s'", pid, d);
+
+        free(d);
+        assert_se(get_process_cmdline(pid, 1, false, &d) >= 0);
+        log_info("PID"PID_FMT" cmdline truncated to 1: '%s'", pid, d);
 
         assert_se(get_process_ppid(pid, &e) >= 0);
         log_info("PID"PID_FMT" PPID: "PID_FMT, pid, e);
@@ -147,6 +155,187 @@ static void test_personality(void) {
 #endif
 }
 
+static void test_get_process_cmdline_harder(void) {
+        char path[] = "/tmp/test-cmdlineXXXXXX";
+        _cleanup_close_ int fd = -1;
+        _cleanup_free_ char *line = NULL;
+        pid_t pid;
+
+        if (geteuid() != 0)
+                return;
+
+        pid = fork();
+        if (pid > 0) {
+                siginfo_t si;
+
+                (void) wait_for_terminate(pid, &si);
+
+                assert_se(si.si_code == CLD_EXITED);
+                assert_se(si.si_status == 0);
+
+                return;
+        }
+
+        assert_se(pid == 0);
+        assert_se(unshare(CLONE_NEWNS) >= 0);
+
+        fd = mkostemp(path, O_CLOEXEC);
+        assert_se(fd >= 0);
+        assert_se(mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) >= 0);
+        assert_se(unlink(path) >= 0);
+
+        assert_se(prctl(PR_SET_NAME, "testa") >= 0);
+
+        assert_se(get_process_cmdline(getpid(), 0, false, &line) == -ENOENT);
+
+        assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
+        assert_se(streq(line, "[testa]"));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 1, true, &line) >= 0);
+        assert_se(streq(line, ""));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 2, true, &line) >= 0);
+        assert_se(streq(line, "["));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 3, true, &line) >= 0);
+        assert_se(streq(line, "[."));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 4, true, &line) >= 0);
+        assert_se(streq(line, "[.."));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 5, true, &line) >= 0);
+        assert_se(streq(line, "[..."));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 6, true, &line) >= 0);
+        assert_se(streq(line, "[...]"));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 7, true, &line) >= 0);
+        assert_se(streq(line, "[t...]"));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 8, true, &line) >= 0);
+        assert_se(streq(line, "[testa]"));
+        line = mfree(line);
+
+        assert_se(write(fd, "\0\0\0\0\0\0\0\0\0", 10) == 10);
+
+        assert_se(get_process_cmdline(getpid(), 0, false, &line) == -ENOENT);
+
+        assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
+        assert_se(streq(line, "[testa]"));
+        line = mfree(line);
+
+        assert_se(write(fd, "foo\0bar\0\0\0\0\0", 10) == 10);
+
+        assert_se(get_process_cmdline(getpid(), 0, false, &line) >= 0);
+        assert_se(streq(line, "foo bar"));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
+        assert_se(streq(line, "foo bar"));
+        line = mfree(line);
+
+        assert_se(write(fd, "quux", 4) == 4);
+        assert_se(get_process_cmdline(getpid(), 0, false, &line) >= 0);
+        assert_se(streq(line, "foo bar quux"));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
+        assert_se(streq(line, "foo bar quux"));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 1, true, &line) >= 0);
+        assert_se(streq(line, ""));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 2, true, &line) >= 0);
+        assert_se(streq(line, "."));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 3, true, &line) >= 0);
+        assert_se(streq(line, ".."));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 4, true, &line) >= 0);
+        assert_se(streq(line, "..."));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 5, true, &line) >= 0);
+        assert_se(streq(line, "f..."));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 6, true, &line) >= 0);
+        assert_se(streq(line, "fo..."));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 7, true, &line) >= 0);
+        assert_se(streq(line, "foo..."));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 8, true, &line) >= 0);
+        assert_se(streq(line, "foo..."));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 9, true, &line) >= 0);
+        assert_se(streq(line, "foo b..."));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 10, true, &line) >= 0);
+        assert_se(streq(line, "foo ba..."));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 11, true, &line) >= 0);
+        assert_se(streq(line, "foo bar..."));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 12, true, &line) >= 0);
+        assert_se(streq(line, "foo bar..."));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 13, true, &line) >= 0);
+        assert_se(streq(line, "foo bar quux"));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 14, true, &line) >= 0);
+        assert_se(streq(line, "foo bar quux"));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 1000, true, &line) >= 0);
+        assert_se(streq(line, "foo bar quux"));
+        line = mfree(line);
+
+        assert_se(ftruncate(fd, 0) >= 0);
+        assert_se(prctl(PR_SET_NAME, "aaaa bbbb cccc") >= 0);
+
+        assert_se(get_process_cmdline(getpid(), 0, false, &line) == -ENOENT);
+
+        assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
+        assert_se(streq(line, "[aaaa bbbb cccc]"));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 10, true, &line) >= 0);
+        assert_se(streq(line, "[aaaa...]"));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 11, true, &line) >= 0);
+        assert_se(streq(line, "[aaaa...]"));
+        line = mfree(line);
+
+        assert_se(get_process_cmdline(getpid(), 12, true, &line) >= 0);
+        assert_se(streq(line, "[aaaa b...]"));
+        line = mfree(line);
+
+        safe_close(fd);
+        _exit(0);
+}
+
 int main(int argc, char *argv[]) {
         log_parse_environment();
         log_open();
@@ -164,6 +353,7 @@ int main(int argc, char *argv[]) {
         test_pid_is_unwaited();
         test_pid_is_alive();
         test_personality();
+        test_get_process_cmdline_harder();
 
         return 0;
 }
index 1a439bd0d47c7ec9ae4ee85548aa00311f3ddce5..1f853a7f16b24fdfc9dba579ded0c0b6ef30481f 100644 (file)
@@ -353,7 +353,7 @@ static void test_nameinfo_pretty(void) {
         union sockaddr_union s = {
                 .in.sin_family = AF_INET,
                 .in.sin_port = 0,
-                .in.sin_addr.s_addr = htonl(INADDR_ANY),
+                .in.sin_addr.s_addr = htobe32(INADDR_ANY),
         };
         int r;
 
@@ -391,17 +391,17 @@ static void test_sockaddr_equal(void) {
         union sockaddr_union a = {
                 .in.sin_family = AF_INET,
                 .in.sin_port = 0,
-                .in.sin_addr.s_addr = htonl(INADDR_ANY),
+                .in.sin_addr.s_addr = htobe32(INADDR_ANY),
         };
         union sockaddr_union b = {
                 .in.sin_family = AF_INET,
                 .in.sin_port = 0,
-                .in.sin_addr.s_addr = htonl(INADDR_ANY),
+                .in.sin_addr.s_addr = htobe32(INADDR_ANY),
         };
         union sockaddr_union c = {
                 .in.sin_family = AF_INET,
                 .in.sin_port = 0,
-                .in.sin_addr.s_addr = htonl(1234),
+                .in.sin_addr.s_addr = htobe32(1234),
         };
         union sockaddr_union d = {
                 .in6.sin6_family = AF_INET6,
index 66b51c1209e9f6d244f436e088fef61df32570e1..6753c52005ad1c4d8b3f5a1a7d2e86bc1426b6c5 100644 (file)
@@ -433,17 +433,13 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) {
                 case QUERY_PROPERTY:
                         list_entry = udev_device_get_properties_list_entry(device);
                         while (list_entry != NULL) {
-                                if (export) {
-                                        const char *prefix = export_prefix;
-
-                                        if (prefix == NULL)
-                                                prefix = "";
-                                        printf("%s%s='%s'\n", prefix,
+                                if (export)
+                                        printf("%s%s='%s'\n", strempty(export_prefix),
                                                udev_list_entry_get_name(list_entry),
                                                udev_list_entry_get_value(list_entry));
-                                } else {
+                                else
                                         printf("%s=%s\n", udev_list_entry_get_name(list_entry), udev_list_entry_get_value(list_entry));
-                                }
+
                                 list_entry = udev_list_entry_get_next(list_entry);
                         }
                         break;