chiark / gitweb /
Merge commit 'b39a2770ba55637da80e2e389222c59dbea73507'
authorLennart Poettering <lennart@poettering.net>
Fri, 15 Aug 2014 18:25:10 +0000 (20:25 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 15 Aug 2014 18:25:10 +0000 (20:25 +0200)
30 files changed:
TODO
man/systemd.network.xml
src/core/cgroup.c
src/core/main.c
src/hostname/hostnamectl.c
src/hostname/hostnamed.c
src/kernel-install/90-loaderentry.install
src/libsystemd/sd-bus/bus-convenience.c
src/libsystemd/sd-bus/bus-objects.c
src/libsystemd/sd-bus/bus-util.c
src/libsystemd/sd-bus/bus-util.h
src/libsystemd/sd-network/sd-network.c
src/locale/localed.c
src/login/logind-dbus.c
src/network/networkctl.c
src/network/networkd-link.c
src/network/networkd-manager.c
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd.h
src/resolve/resolved-dns-scope.c
src/resolve/resolved-dns-stream.c
src/resolve/resolved-manager.c
src/shared/log.c
src/shared/macro.h
src/shared/util.c
src/systemd/sd-bus.h
src/systemd/sd-network.h
src/test/test-util.c
src/timedate/timedated.c

diff --git a/TODO b/TODO
index 8d3c1ca..e85eb55 100644 (file)
--- a/TODO
+++ b/TODO
@@ -24,6 +24,15 @@ External:
 
 Features:
 
+* sd_notify("SHUTDOWN=1") to fix a dbus activation race.
+  http://lists.freedesktop.org/archives/systemd-devel/2014-July/020983.html
+
+* merge ~/.local/share and ~/.local/lib into one similar /usr/lib and /usr/share....
+
+* make "systemctl suspend" block until we are back from suspend
+
+* remove readahead in 217
+
 * journald: allows specification of UID range for splitting up journal files
 
 * systemd.show_status= should probably have a mode where only failed
index 290aa6e..0245099 100644 (file)
                                                 This option may be specified more than once.</para>
                                         </listitem>
                                 </varlistentry>
-<!-- TODO: document NTP= option when it is actually used somewhere -->
+                                <varlistentry>
+                                        <term><varname>Domains=</varname></term>
+                                        <listitem>
+                                                <para>The domains used for DNS resolution over this link.</para>
+                                        </listitem>
+                                </varlistentry>
+                                <varlistentry>
+                                        <term><varname>NTP=</varname></term>
+                                        <listitem>
+                                                <para>An NTP server address. This option may be specified more than once.</para>
+                                        </listitem>
+                                </varlistentry>
                                 <varlistentry>
                                         <term><varname>Bridge=</varname></term>
                                         <listitem>
index 42bf09f..9248cb5 100644 (file)
@@ -199,7 +199,8 @@ static int whitelist_device(const char *path, const char *node, const char *acc)
                 acc);
 
         r = cg_set_attribute("devices", path, "devices.allow", buf);
-        log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set devices.allow on %s: %s", path, strerror(-r));
+        if (r < 0)
+                log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set devices.allow on %s: %s", path, strerror(-r));
 
         return r;
 }
@@ -270,7 +271,8 @@ static int whitelist_major(const char *path, const char *name, char type, const
                         acc);
 
                 r = cg_set_attribute("devices", path, "devices.allow", buf);
-                log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set devices.allow on %s: %s", path, strerror(-r));
+                if (r < 0)
+                        log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set devices.allow on %s: %s", path, strerror(-r));
         }
 
         return 0;
@@ -301,18 +303,21 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha
                         state == MANAGER_STARTING && c->startup_cpu_shares != (unsigned long) -1 ? c->startup_cpu_shares :
                         c->cpu_shares != (unsigned long) -1 ? c->cpu_shares : 1024);
                 r = cg_set_attribute("cpu", path, "cpu.shares", buf);
-                log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set cpu.shares on %s: %s", path, strerror(-r));
+                if (r < 0)
+                        log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set cpu.shares on %s: %s", path, strerror(-r));
 
                 sprintf(buf, USEC_FMT "\n", CGROUP_CPU_QUOTA_PERIOD_USEC);
                 r = cg_set_attribute("cpu", path, "cpu.cfs_period_us", buf);
-                log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set cpu.cfs_period_us on %s: %s", path, strerror(-r));
+                if (r < 0)
+                        log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set cpu.cfs_period_us on %s: %s", path, strerror(-r));
 
                 if (c->cpu_quota_per_sec_usec != USEC_INFINITY) {
                         sprintf(buf, USEC_FMT "\n", c->cpu_quota_per_sec_usec * CGROUP_CPU_QUOTA_PERIOD_USEC / USEC_PER_SEC);
                         r = cg_set_attribute("cpu", path, "cpu.cfs_quota_us", buf);
                 } else
                         r = cg_set_attribute("cpu", path, "cpu.cfs_quota_us", "-1");
-                log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set cpu.cfs_quota_us on %s: %s", path, strerror(-r));
+                if (r < 0)
+                        log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set cpu.cfs_quota_us on %s: %s", path, strerror(-r));
         }
 
         if (mask & CGROUP_BLKIO) {
@@ -326,7 +331,8 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha
                         sprintf(buf, "%lu\n", state == MANAGER_STARTING && c->startup_blockio_weight != (unsigned long) -1 ? c->startup_blockio_weight :
                                 c->blockio_weight != (unsigned long) -1 ? c->blockio_weight : 1000);
                         r = cg_set_attribute("blkio", path, "blkio.weight", buf);
-                        log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set blkio.weight on %s: %s", path, strerror(-r));
+                        if (r < 0)
+                                log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set blkio.weight on %s: %s", path, strerror(-r));
 
                         /* FIXME: no way to reset this list */
                         LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
@@ -338,7 +344,8 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha
 
                                 sprintf(buf, "%u:%u %lu", major(dev), minor(dev), w->weight);
                                 r = cg_set_attribute("blkio", path, "blkio.weight_device", buf);
-                                log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set blkio.weight_device on %s: %s", path, strerror(-r));
+                                if (r < 0)
+                                        log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set blkio.weight_device on %s: %s", path, strerror(-r));
                         }
                 }
 
@@ -355,7 +362,8 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha
 
                         sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), b->bandwidth);
                         r = cg_set_attribute("blkio", path, a, buf);
-                        log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set %s on %s: %s", a, path, strerror(-r));
+                        if (r < 0)
+                                log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set %s on %s: %s", a, path, strerror(-r));
                 }
         }
 
@@ -368,7 +376,8 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha
                 } else
                         r = cg_set_attribute("memory", path, "memory.limit_in_bytes", "-1");
 
-                log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r));
+                if (r < 0)
+                        log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r));
         }
 
         if ((mask & CGROUP_DEVICE) && !is_root) {
@@ -378,7 +387,8 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha
                         r = cg_set_attribute("devices", path, "devices.deny", "a");
                 else
                         r = cg_set_attribute("devices", path, "devices.allow", "a");
-                log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to reset devices.list on %s: %s", path, strerror(-r));
+                if (r < 0)
+                        log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to reset devices.list on %s: %s", path, strerror(-r));
 
                 if (c->device_policy == CGROUP_CLOSED ||
                     (c->device_policy == CGROUP_AUTO && c->device_allow)) {
index f33b78d..792b316 100644 (file)
@@ -228,31 +228,25 @@ static void install_crash_handler(void) {
         sigaction_many(&sa, SIGNALS_CRASH_HANDLER, -1);
 }
 
-static int console_setup(bool do_reset) {
-        int tty_fd, r;
-
-        /* If we are init, we connect stdin/stdout/stderr to /dev/null
-         * and make sure we don't have a controlling tty. */
-
-        release_terminal();
-
-        if (!do_reset)
-                return 0;
+static int console_setup(void) {
+        _cleanup_close_ int tty_fd = -1;
+        int r;
 
         tty_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
         if (tty_fd < 0) {
                 log_error("Failed to open /dev/console: %s", strerror(-tty_fd));
-                return -tty_fd;
+                return tty_fd;
         }
 
-        /* We don't want to force text mode.
-         * plymouth may be showing pictures already from initrd. */
+        /* We don't want to force text mode.  plymouth may be showing
+         * pictures already from initrd. */
         r = reset_terminal_fd(tty_fd, false);
-        if (r < 0)
+        if (r < 0) {
                 log_error("Failed to reset /dev/console: %s", strerror(-r));
+                return r;
+        }
 
-        safe_close(tty_fd);
-        return r;
+        return 0;
 }
 
 static int set_default_unit(const char *u) {
@@ -299,26 +293,6 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
                 if (in_initrd())
                         return set_default_unit(value);
 
-        } else if (streq(key, "systemd.log_target") && value) {
-
-                if (log_set_target_from_string(value) < 0)
-                        log_warning("Failed to parse log target %s. Ignoring.", value);
-
-        } else if (streq(key, "systemd.log_level") && value) {
-
-                if (log_set_max_level_from_string(value) < 0)
-                        log_warning("Failed to parse log level %s. Ignoring.", value);
-
-        } else if (streq(key, "systemd.log_color") && value) {
-
-                if (log_show_color_from_string(value) < 0)
-                        log_warning("Failed to parse log color setting %s. Ignoring.", value);
-
-        } else if (streq(key, "systemd.log_location") && value) {
-
-                if (log_show_location_from_string(value) < 0)
-                        log_warning("Failed to parse log location setting %s. Ignoring.", value);
-
         } else if (streq(key, "systemd.dump_core") && value) {
 
                 r = parse_boolean(value);
@@ -394,7 +368,8 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
 
         } else if (streq(key, "debug") && !value) {
 
-                log_set_max_level(LOG_DEBUG);
+                /* Note that log_parse_environment() handles 'debug'
+                 * too, and sets the log level to LOG_DEBUG. */
 
                 if (detect_container(NULL) > 0)
                         log_set_target(LOG_TARGET_CONSOLE);
@@ -969,37 +944,6 @@ static int parse_argv(int argc, char *argv[]) {
                 return -EINVAL;
         }
 
-        if (detect_container(NULL) > 0) {
-                char **a;
-
-                /* All /proc/cmdline arguments the kernel didn't
-                 * understand it passed to us. We're not really
-                 * interested in that usually since /proc/cmdline is
-                 * more interesting and complete. With one exception:
-                 * if we are run in a container /proc/cmdline is not
-                 * relevant for the container, hence we rely on argv[]
-                 * instead. */
-
-                for (a = argv; a < argv + argc; a++) {
-                        _cleanup_free_ char *w;
-                        char *value;
-
-                        w = strdup(*a);
-                        if (!w)
-                                return log_oom();
-
-                        value = strchr(w, '=');
-                        if (value)
-                                *(value++) = 0;
-
-                        r = parse_proc_cmdline_item(w, value);
-                        if (r < 0) {
-                                log_error("Failed on cmdline argument %s: %s", *a, strerror(-r));
-                                return r;
-                        }
-                }
-        }
-
         return 0;
 }
 
@@ -1461,6 +1405,8 @@ int main(int argc, char *argv[]) {
                 if (parse_proc_cmdline(parse_proc_cmdline_item) < 0)
                         goto finish;
 
+        /* Note that this also parses bits from the kernel command
+         * line, including "debug". */
         log_parse_environment();
 
         if (parse_argv(argc, argv) < 0)
@@ -1537,8 +1483,16 @@ int main(int argc, char *argv[]) {
 
         /* Reset the console, but only if this is really init and we
          * are freshly booted */
-        if (arg_running_as == SYSTEMD_SYSTEM && arg_action == ACTION_RUN)
-                console_setup(getpid() == 1 && !skip_setup);
+        if (arg_running_as == SYSTEMD_SYSTEM && arg_action == ACTION_RUN) {
+
+                /* If we are init, we connect stdin/stdout/stderr to
+                 * /dev/null and make sure we don't have a controlling
+                 * tty. */
+                release_terminal();
+
+                if (getpid() == 1 && !skip_setup)
+                        console_setup();
+        }
 
         /* Open the logging devices, if possible and necessary */
         log_open();
index f8e1a81..e487369 100644 (file)
@@ -68,6 +68,7 @@ typedef struct StatusInfo {
         char *icon_name;
         char *chassis;
         char *deployment;
+        char *location;
         char *kernel_name;
         char *kernel_release;
         char *os_pretty_name;
@@ -92,12 +93,19 @@ static void print_status_info(StatusInfo *i) {
             !streq_ptr(i->hostname, i->static_hostname))
                 printf("Transient hostname: %s\n", i->hostname);
 
-        printf("         Icon name: %s\n"
-               "           Chassis: %s\n"
-               "        Deployment: %s\n",
-               strna(i->icon_name),
-               strna(i->chassis),
-               strna(i->deployment));
+        if (!isempty(i->icon_name))
+                printf("         Icon name: %s\n",
+                       strna(i->icon_name));
+
+        if (!isempty(i->chassis))
+                printf("           Chassis: %s\n",
+                       strna(i->chassis));
+
+        if (!isempty(i->deployment))
+                printf("        Deployment: %s\n", i->deployment);
+
+        if (!isempty(i->location))
+                printf("          Location: %s\n", i->location);
 
         r = sd_id128_get_machine(&mid);
         if (r >= 0)
@@ -155,22 +163,23 @@ static int show_all_names(sd_bus *bus) {
         StatusInfo info = {};
 
         static const struct bus_properties_map hostname_map[]  = {
-                { "Hostname",       "s", NULL, offsetof(StatusInfo, hostname) },
-                { "StaticHostname", "s", NULL, offsetof(StatusInfo, static_hostname) },
-                { "PrettyHostname", "s", NULL, offsetof(StatusInfo, pretty_hostname) },
-                { "IconName",       "s", NULL, offsetof(StatusInfo, icon_name) },
-                { "Chassis",        "s", NULL, offsetof(StatusInfo, chassis) },
-                { "Deployment",        "s", NULL, offsetof(StatusInfo, deployment) },
-                { "KernelName",     "s", NULL, offsetof(StatusInfo, kernel_name) },
-                { "KernelRelease",     "s", NULL, offsetof(StatusInfo, kernel_release) },
-                { "OperatingSystemPrettyName",     "s", NULL, offsetof(StatusInfo, os_pretty_name) },
-                { "OperatingSystemCPEName",        "s", NULL, offsetof(StatusInfo, os_cpe_name) },
+                { "Hostname",                  "s", NULL, offsetof(StatusInfo, hostname)        },
+                { "StaticHostname",            "s", NULL, offsetof(StatusInfo, static_hostname) },
+                { "PrettyHostname",            "s", NULL, offsetof(StatusInfo, pretty_hostname) },
+                { "IconName",                  "s", NULL, offsetof(StatusInfo, icon_name)       },
+                { "Chassis",                   "s", NULL, offsetof(StatusInfo, chassis)         },
+                { "Deployment",                "s", NULL, offsetof(StatusInfo, deployment)      },
+                { "Location",                  "s", NULL, offsetof(StatusInfo, location)        },
+                { "KernelName",                "s", NULL, offsetof(StatusInfo, kernel_name)     },
+                { "KernelRelease",             "s", NULL, offsetof(StatusInfo, kernel_release)  },
+                { "OperatingSystemPrettyName", "s", NULL, offsetof(StatusInfo, os_pretty_name)  },
+                { "OperatingSystemCPEName",    "s", NULL, offsetof(StatusInfo, os_cpe_name)     },
                 {}
         };
 
         static const struct bus_properties_map manager_map[] = {
-                { "Virtualization", "s", NULL, offsetof(StatusInfo, virtualization) },
-                { "Architecture",   "s", NULL, offsetof(StatusInfo, architecture) },
+                { "Virtualization",            "s", NULL, offsetof(StatusInfo, virtualization)  },
+                { "Architecture",              "s", NULL, offsetof(StatusInfo, architecture)    },
                 {}
         };
 
@@ -199,6 +208,7 @@ fail:
         free(info.icon_name);
         free(info.chassis);
         free(info.deployment);
+        free(info.location);
         free(info.kernel_name);
         free(info.kernel_release);
         free(info.os_pretty_name);
@@ -321,6 +331,13 @@ static int set_deployment(sd_bus *bus, char **args, unsigned n) {
         return set_simple_string(bus, "SetDeployment", args[1]);
 }
 
+static int set_location(sd_bus *bus, char **args, unsigned n) {
+        assert(args);
+        assert(n == 2);
+
+        return set_simple_string(bus, "SetLocation", args[1]);
+}
+
 static void help(void) {
         printf("%s [OPTIONS...] COMMAND ...\n\n"
                "Query or change system hostname.\n\n"
@@ -338,6 +355,7 @@ static void help(void) {
                "  set-icon-name NAME     Set icon name for host\n"
                "  set-chassis NAME       Set chassis type for host\n"
                "  set-deployment NAME    Set deployment environment for host\n"
+               "  set-location NAME      Set location for host\n"
                , program_invocation_short_name);
 }
 
@@ -429,11 +447,12 @@ static int hostnamectl_main(sd_bus *bus, int argc, char *argv[]) {
                 const int argc;
                 int (* const dispatch)(sd_bus *bus, char **args, unsigned n);
         } verbs[] = {
-                { "status",        LESS,  1, show_status   },
-                { "set-hostname",  EQUAL, 2, set_hostname  },
-                { "set-icon-name", EQUAL, 2, set_icon_name },
-                { "set-chassis",   EQUAL, 2, set_chassis   },
-                { "set-deployment",   EQUAL, 2, set_deployment   },
+                { "status",           LESS,  1, show_status    },
+                { "set-hostname",     EQUAL, 2, set_hostname   },
+                { "set-icon-name",    EQUAL, 2, set_icon_name  },
+                { "set-chassis",      EQUAL, 2, set_chassis    },
+                { "set-deployment",   EQUAL, 2, set_deployment },
+                { "set-location",     EQUAL, 2, set_location   },
         };
 
         int left;
index a6f440f..c7f738a 100644 (file)
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/utsname.h>
+#include <sys/capability.h>
 
 #include "util.h"
 #include "strv.h"
@@ -425,7 +426,7 @@ static int method_set_hostname(sd_bus *bus, sd_bus_message *m, void *userdata, s
         if (streq_ptr(name, c->data[PROP_HOSTNAME]))
                 return sd_bus_reply_method_return(m, NULL);
 
-        r = bus_verify_polkit_async(bus, &c->polkit_registry, m, "org.freedesktop.hostname1.set-hostname", interactive, error, method_set_hostname, c);
+        r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_ADMIN, "org.freedesktop.hostname1.set-hostname", interactive, error, method_set_hostname, c);
         if (r < 0)
                 return r;
         if (r == 0)
@@ -467,7 +468,7 @@ static int method_set_static_hostname(sd_bus *bus, sd_bus_message *m, void *user
         if (streq_ptr(name, c->data[PROP_STATIC_HOSTNAME]))
                 return sd_bus_reply_method_return(m, NULL);
 
-        r = bus_verify_polkit_async(bus, &c->polkit_registry, m, "org.freedesktop.hostname1.set-static-hostname", interactive, error, method_set_static_hostname, c);
+        r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_ADMIN, "org.freedesktop.hostname1.set-static-hostname", interactive, error, method_set_static_hostname, c);
         if (r < 0)
                 return r;
         if (r == 0)
@@ -532,9 +533,10 @@ static int set_machine_info(Context *c, sd_bus *bus, sd_bus_message *m, int prop
          * same time as the static one, use the same policy action for
          * both... */
 
-        r = bus_verify_polkit_async(bus, &c->polkit_registry, m, prop == PROP_PRETTY_HOSTNAME ?
-                          "org.freedesktop.hostname1.set-static-hostname" :
-                          "org.freedesktop.hostname1.set-machine-info", interactive, error, cb, c);
+        r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_ADMIN,
+                                    prop == PROP_PRETTY_HOSTNAME ?
+                                    "org.freedesktop.hostname1.set-static-hostname" :
+                                    "org.freedesktop.hostname1.set-machine-info", interactive, error, cb, c);
         if (r < 0)
                 return r;
         if (r == 0)
index c17b8a9..6f032b5 100644 (file)
@@ -47,11 +47,10 @@ if [[ -f /etc/kernel/cmdline ]]; then
 fi
 
 if ! [[ ${BOOT_OPTIONS[*]} ]]; then
-    readarray -t line < /proc/cmdline
-    for i in ${line[*]}; do
-        if [[ "${i#initrd=*}" == "$i" ]]; then
-            BOOT_OPTIONS[${#BOOT_OPTIONS[@]}]="$i"
-        fi
+    read -ar line < /proc/cmdline
+    for i in "${line[@]}"; do
+        [[ "${i#initrd=*}" != "$i" ]] && continue
+        BOOT_OPTIONS[${#BOOT_OPTIONS[@]}]="$i"
     done
 fi
 
index c5b9cd4..f88836b 100644 (file)
@@ -472,3 +472,56 @@ _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_b
 
         return bus_creds_extend_by_pid(c, mask, creds);
 }
+
+_public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) {
+        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        uid_t our_uid;
+        int r;
+
+        assert_return(call, -EINVAL);
+        assert_return(call->sealed, -EPERM);
+        assert_return(call->bus, -EINVAL);
+        assert_return(!bus_pid_changed(call->bus), -ECHILD);
+
+        if (!BUS_IS_OPEN(call->bus->state))
+                return -ENOTCONN;
+
+        /* We only trust the effective capability set if this is
+         * kdbus. On classic dbus1 we cannot retrieve the value
+         * without races. Since this function is supposed to be useful
+         * for authentication decision we hence avoid requesting and
+         * using that information. */
+        if (call->bus->is_kernel && capability >= 0) {
+                r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_creds_has_effective_cap(creds, capability);
+                if (r > 0)
+                        return 1;
+        } else {
+                r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID, &creds);
+                if (r < 0)
+                        return r;
+        }
+
+        /* Now, check the UID, but only if the capability check wasn't
+         * sufficient */
+        our_uid = getuid();
+        if (our_uid != 0 || !call->bus->is_kernel || capability < 0) {
+                uid_t sender_uid;
+
+                r = sd_bus_creds_get_uid(creds, &sender_uid);
+                if (r >= 0) {
+                        /* Sender has same UID as us, then let's grant access */
+                        if (sender_uid == our_uid)
+                                return 1;
+
+                        /* Sender is root, we are not root. */
+                        if (our_uid != 0 && sender_uid == 0)
+                                return 1;
+                }
+        }
+
+        return 0;
+}
index dbb04e5..78dab80 100644 (file)
@@ -289,7 +289,6 @@ static int node_callbacks_run(
 static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c, sd_bus_error *error) {
         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
         uint64_t cap;
-        uid_t uid;
         int r;
 
         assert(bus);
@@ -304,17 +303,6 @@ static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c,
         if (c->vtable->flags & SD_BUS_VTABLE_UNPRIVILEGED)
                 return 0;
 
-        /* If we are not connected to kdbus we cannot retrieve the
-         * effective capability set without race. Since we need this
-         * for a security decision we cannot use racy data, hence
-         * don't request it. */
-        if (bus->is_kernel)
-                r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds);
-        else
-                r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds);
-        if (r < 0)
-                return r;
-
         /* Check have the caller has the requested capability
          * set. Note that the flags value contains the capability
          * number plus one, which we need to subtract here. We do this
@@ -328,16 +316,11 @@ static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c,
         else
                 cap --;
 
-        r = sd_bus_creds_has_effective_cap(creds, cap);
+        r = sd_bus_query_sender_privilege(m, cap);
+        if (r < 0)
+                return r;
         if (r > 0)
-                return 1;
-
-        /* Caller has same UID as us, then let's grant access */
-        r = sd_bus_creds_get_uid(creds, &uid);
-        if (r >= 0) {
-                if (uid == getuid())
-                        return 1;
-        }
+                return 0;
 
         return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Access to %s.%s() not permitted.", c->interface, c->member);
 }
index 37f5c46..65f1d17 100644 (file)
@@ -186,28 +186,22 @@ int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
 int bus_verify_polkit(
                 sd_bus *bus,
                 sd_bus_message *m,
+                int capability,
                 const char *action,
                 bool interactive,
                 bool *_challenge,
                 sd_bus_error *e) {
 
-        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
-        uid_t uid;
         int r;
 
         assert(bus);
         assert(m);
         assert(action);
 
-        r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds);
+        r = sd_bus_query_sender_privilege(m, capability);
         if (r < 0)
                 return r;
-
-        r = sd_bus_creds_get_uid(creds, &uid);
-        if (r < 0)
-                return r;
-
-        if (uid == 0)
+        if (r > 0)
                 return 1;
 
 #ifdef ENABLE_POLKIT
@@ -325,6 +319,7 @@ int bus_verify_polkit_async(
                 sd_bus *bus,
                 Hashmap **registry,
                 sd_bus_message *m,
+                int capability,
                 const char *action,
                 bool interactive,
                 sd_bus_error *error,
@@ -336,8 +331,6 @@ int bus_verify_polkit_async(
         AsyncPolkitQuery *q;
         const char *sender;
 #endif
-        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
-        uid_t uid;
         int r;
 
         assert(bus);
@@ -383,15 +376,10 @@ int bus_verify_polkit_async(
         }
 #endif
 
-        r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds);
+        r = sd_bus_query_sender_privilege(m, capability);
         if (r < 0)
                 return r;
-
-        r = sd_bus_creds_get_uid(creds, &uid);
-        if (r < 0)
-                return r;
-
-        if (uid == 0)
+        if (r > 0)
                 return 1;
 
 #ifdef ENABLE_POLKIT
index b3b52af..1ac4687 100644 (file)
@@ -62,9 +62,9 @@ int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error);
 
 int bus_check_peercred(sd_bus *c);
 
-int bus_verify_polkit(sd_bus *bus, sd_bus_message *m, const char *action, bool interactive, bool *_challenge, sd_bus_error *e);
+int bus_verify_polkit(sd_bus *bus, sd_bus_message *m, int capability, const char *action, bool interactive, bool *_challenge, sd_bus_error *e);
 
-int bus_verify_polkit_async(sd_bus *bus, Hashmap **registry, sd_bus_message *m, const char *action, bool interactive, sd_bus_error *error, sd_bus_message_handler_t callback, void *userdata);
+int bus_verify_polkit_async(sd_bus *bus, Hashmap **registry, sd_bus_message *m, int capability, const char *action, bool interactive, sd_bus_error *error, sd_bus_message_handler_t callback, void *userdata);
 void bus_verify_polkit_async_registry_free(Hashmap *registry);
 
 int bus_open_system_systemd(sd_bus **_bus);
index 4d8b7e7..3a3f535 100644 (file)
@@ -92,6 +92,10 @@ _public_ int sd_network_get_ntp(char ***ret) {
         return network_get_strv("NTP", ret);
 }
 
+_public_ int sd_network_get_domains(char ***ret) {
+        return network_get_strv("DOMAINS", ret);
+}
+
 _public_ int sd_network_link_get_setup_state(int ifindex, char **state) {
         _cleanup_free_ char *s = NULL, *p = NULL;
         int r;
@@ -210,6 +214,26 @@ _public_ int sd_network_link_get_domains(int ifindex, char ***ret) {
         return network_get_link_strv("DOMAINS", ifindex, ret);
 }
 
+_public_ int sd_network_link_get_wildcard_domain(int ifindex) {
+        int r;
+        _cleanup_free_ char *p = NULL, *s = NULL;
+
+        assert_return(ifindex > 0, -EINVAL);
+
+        if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
+                return -ENOMEM;
+
+        r = parse_env_file(p, NEWLINE, "WILDCARD_DOMAIN", &s, NULL);
+        if (r == -ENOENT)
+                return -ENODATA;
+        if (r < 0)
+                return r;
+        if (isempty(s))
+                return -ENODATA;
+
+        return parse_boolean(s);
+}
+
 static inline int MONITOR_TO_FD(sd_network_monitor *m) {
         return (int) (unsigned long) m - 1;
 }
index 4d7d02b..5c0bc2c 100644 (file)
@@ -23,6 +23,7 @@
 #include <errno.h>
 #include <string.h>
 #include <unistd.h>
+#include <sys/capability.h>
 
 #include "sd-bus.h"
 
@@ -876,7 +877,7 @@ static int method_set_locale(sd_bus *bus, sd_bus_message *m, void *userdata, sd_
         }
 
         if (modified) {
-                r = bus_verify_polkit_async(bus, &c->polkit_registry, m,
+                r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_ADMIN,
                                             "org.freedesktop.locale1.set-locale", interactive,
                                             error, method_set_locale, c);
                 if (r < 0)
@@ -954,7 +955,7 @@ static int method_set_vc_keyboard(sd_bus *bus, sd_bus_message *m, void *userdata
                     (keymap_toggle && (!filename_is_safe(keymap_toggle) || !string_is_safe(keymap_toggle))))
                         return sd_bus_error_set_errnof(error, -EINVAL, "Received invalid keymap data");
 
-                r = bus_verify_polkit_async(bus, &c->polkit_registry, m,
+                r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_ADMIN,
                                 "org.freedesktop.locale1.set-keyboard",
                                 interactive, error, method_set_vc_keyboard, c);
                 if (r < 0)
@@ -1026,7 +1027,7 @@ static int method_set_x11_keyboard(sd_bus *bus, sd_bus_message *m, void *userdat
                     (options && !string_is_safe(options)))
                         return sd_bus_error_set_errnof(error, -EINVAL, "Received invalid keyboard data");
 
-                r = bus_verify_polkit_async(bus, &c->polkit_registry, m,
+                r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_ADMIN,
                                 "org.freedesktop.locale1.set-keyboard",
                                 interactive, error, method_set_x11_keyboard, c);
                 if (r < 0)
index 1a363c2..bcfcba2 100644 (file)
@@ -1032,6 +1032,7 @@ static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *us
         r = bus_verify_polkit_async(bus,
                                     &m->polkit_registry,
                                     message,
+                                    CAP_SYS_ADMIN,
                                     "org.freedesktop.login1.set-user-linger",
                                     interactive,
                                     error,
@@ -1204,6 +1205,7 @@ static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *user
         r = bus_verify_polkit_async(bus,
                                     &m->polkit_registry,
                                     message,
+                                    CAP_SYS_ADMIN,
                                     "org.freedesktop.login1.attach-device",
                                     interactive,
                                     error,
@@ -1235,6 +1237,7 @@ static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *user
         r = bus_verify_polkit_async(bus,
                                     &m->polkit_registry,
                                     message,
+                                    CAP_SYS_ADMIN,
                                     "org.freedesktop.login1.flush-devices",
                                     interactive,
                                     error,
@@ -1532,7 +1535,7 @@ static int method_do_shutdown_or_sleep(
         blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
 
         if (multiple_sessions) {
-                r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message,
+                r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message, CAP_SYS_BOOT,
                                             action_multiple_sessions, interactive, error, method, m);
                 if (r < 0)
                         return r;
@@ -1541,7 +1544,7 @@ static int method_do_shutdown_or_sleep(
         }
 
         if (blocked) {
-                r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message,
+                r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message, CAP_SYS_BOOT,
                                             action_ignore_inhibit, interactive, error, method, m);
                 if (r < 0)
                         return r;
@@ -1550,7 +1553,7 @@ static int method_do_shutdown_or_sleep(
         }
 
         if (!multiple_sessions && !blocked) {
-                r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message,
+                r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message, CAP_SYS_BOOT,
                                             action, interactive, error, method, m);
                 if (r < 0)
                         return r;
@@ -1688,7 +1691,7 @@ static int method_can_shutdown_or_sleep(
         blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
 
         if (multiple_sessions) {
-                r = bus_verify_polkit(m->bus, message, action_multiple_sessions, false, &challenge, error);
+                r = bus_verify_polkit(m->bus, message, CAP_SYS_BOOT, action_multiple_sessions, false, &challenge, error);
                 if (r < 0)
                         return r;
 
@@ -1701,7 +1704,7 @@ static int method_can_shutdown_or_sleep(
         }
 
         if (blocked) {
-                r = bus_verify_polkit(m->bus, message, action_ignore_inhibit, false, &challenge, error);
+                r = bus_verify_polkit(m->bus, message, CAP_SYS_BOOT, action_ignore_inhibit, false, &challenge, error);
                 if (r < 0)
                         return r;
 
@@ -1717,7 +1720,7 @@ static int method_can_shutdown_or_sleep(
                 /* If neither inhibit nor multiple sessions
                  * apply then just check the normal policy */
 
-                r = bus_verify_polkit(m->bus, message, action, false, &challenge, error);
+                r = bus_verify_polkit(m->bus, message, CAP_SYS_BOOT, action, false, &challenge, error);
                 if (r < 0)
                         return r;
 
@@ -1837,7 +1840,7 @@ static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata,
         if (m->action_what & w)
                 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
 
-        r = bus_verify_polkit_async(bus, &m->polkit_registry, message,
+        r = bus_verify_polkit_async(bus, &m->polkit_registry, message, CAP_SYS_BOOT,
                                     w == INHIBIT_SHUTDOWN             ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
                                     w == INHIBIT_SLEEP                ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep"    : "org.freedesktop.login1.inhibit-delay-sleep") :
                                     w == INHIBIT_IDLE                 ? "org.freedesktop.login1.inhibit-block-idle" :
index 33fe8bf..6253cbf 100644 (file)
@@ -366,6 +366,17 @@ static int link_status_one(sd_rtnl *rtnl, struct udev *udev, const char *name) {
         sd_network_link_get_dns(ifindex, &dns);
         sd_network_link_get_ntp(ifindex, &ntp);
         sd_network_link_get_domains(ifindex, &domains);
+        r = sd_network_link_get_wildcard_domain(ifindex);
+        if (r > 0) {
+                char *wildcard;
+
+                wildcard = strdup("*");
+                if (!wildcard)
+                        return log_oom();
+
+                if (strv_consume(&domains, wildcard) < 0)
+                        return log_oom();
+        }
 
         sprintf(devid, "n%i", ifindex);
         d = udev_device_new_from_device_id(udev, devid);
@@ -416,7 +427,7 @@ static int link_status_one(sd_rtnl *rtnl, struct udev *udev, const char *name) {
         if (!strv_isempty(dns))
                 dump_list("         DNS: ", dns);
         if (!strv_isempty(domains))
-                dump_list("     Domains: ", domains);
+                dump_list("      Domain: ", domains);
         if (!strv_isempty(ntp))
                 dump_list("         NTP: ", ntp);
 
@@ -443,7 +454,7 @@ static int link_status(char **args, unsigned n) {
 
         if (n <= 1 && !arg_all) {
                 _cleanup_free_ char *operational_state = NULL;
-                _cleanup_strv_free_ char **dns = NULL, **ntp = NULL;
+                _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL;
                 _cleanup_free_ struct local_address *addresses = NULL;
                 const char *on_color_operational, *off_color_operational;
                 int i, c;
@@ -469,6 +480,10 @@ static int link_status(char **args, unsigned n) {
                 if (!strv_isempty(dns))
                         dump_list("         DNS: ", dns);
 
+                sd_network_get_domains(&domains);
+                if (!strv_isempty(domains))
+                        dump_list("      Domain: ", domains);
+
                 sd_network_get_dns(&ntp);
                 if (!strv_isempty(ntp))
                         dump_list("         NTP: ", ntp);
index 9eb2e89..a37561a 100644 (file)
@@ -1722,9 +1722,14 @@ int link_save(Link *link) {
 
         if (link->network) {
                 char **address;
+                char **domain;
 
                 fputs("DNS=", f);
 
+                STRV_FOREACH(address, link->network->dns)
+                        fprintf(f, "%s%s", *address,
+                                (address + 1 ? " " : ""));
+
                 if (link->network->dhcp_dns &&
                     link->dhcp_lease) {
                         const struct in_addr *addresses;
@@ -1737,14 +1742,14 @@ int link_save(Link *link) {
                         }
                 }
 
-                STRV_FOREACH(address, link->network->dns)
-                        fprintf(f, "%s%s", *address,
-                                (address + 1 ? " " : ""));
-
                 fputs("\n", f);
 
                 fprintf(f, "NTP=");
 
+                STRV_FOREACH(address, link->network->ntp)
+                        fprintf(f, "%s%s", *address,
+                                (address + 1 ? " " : ""));
+
                 if (link->network->dhcp_ntp &&
                     link->dhcp_lease) {
                         const struct in_addr *addresses;
@@ -1757,21 +1762,31 @@ int link_save(Link *link) {
                         }
                 }
 
-                STRV_FOREACH(address, link->network->ntp)
-                        fprintf(f, "%s%s", *address,
-                                (address + 1 ? " " : ""));
-
                 fputs("\n", f);
 
+                fprintf(f, "DOMAINS=");
+
+                STRV_FOREACH(domain, link->network->domains)
+                        fprintf(f, "%s%s", *domain,
+                                (domain + 1 ? " " : ""));
+
                 if (link->network->dhcp_domains &&
                     link->dhcp_lease) {
                         const char *domainname;
 
                         r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
-                        if (r >= 0)
-                                fprintf(f, "DOMAINS=%s\n", domainname);
+                        if (r >= 0) {
+                                fputs(domainname, f);
+                                if (link->network->domains)
+                                        fputs(" ", f);
+                        }
                 }
 
+                fputs("\n", f);
+
+                fprintf(f, "WILDCARD_DOMAIN=%s\n",
+                        yes_no(link->network->wildcard_domain));
+
                 fprintf(f, "LLMNR=%s\n",
                         llmnr_support_to_string(link->network->llmnr));
         }
index e3d72ed..f2fe5d5 100644 (file)
@@ -450,8 +450,27 @@ static int set_put_in_addrv(Set *s, const struct in_addr *addresses, int n) {
         return c;
 }
 
+static void print_string_set(FILE *f, const char *field, Set *s) {
+        bool space = false;
+        Iterator i;
+        char *p;
+
+        if (set_isempty(s))
+                return;
+
+        fputs(field, f);
+
+        SET_FOREACH(p, s, i) {
+                if (space)
+                        fputc(' ', f);
+                fputs(p, f);
+                space = true;
+        }
+        fputc('\n', f);
+}
+
 int manager_save(Manager *m) {
-        _cleanup_set_free_free_ Set *dns = NULL, *ntp = NULL;
+        _cleanup_set_free_free_ Set *dns = NULL, *ntp = NULL, *domains = NULL;
         Link *link;
         Iterator i;
         _cleanup_free_ char *temp_path = NULL;
@@ -472,6 +491,10 @@ int manager_save(Manager *m) {
         if (!ntp)
                 return -ENOMEM;
 
+        domains = set_new(string_hash_func, string_compare_func);
+        if (!domains)
+                return -ENOMEM;
+
         HASHMAP_FOREACH(link, m->links, i) {
                 if (link->flags & IFF_LOOPBACK)
                         continue;
@@ -491,6 +514,10 @@ int manager_save(Manager *m) {
                 if (r < 0)
                         return r;
 
+                r = set_put_strdupv(domains, link->network->domains);
+                if (r < 0)
+                        return r;
+
                 if (!link->dhcp_lease)
                         continue;
 
@@ -503,7 +530,7 @@ int manager_save(Manager *m) {
                                 r = set_put_in_addrv(dns, addresses, r);
                                 if (r < 0)
                                         return r;
-                        } else if (r != -ENOENT)
+                        } else if (r < 0 && r != -ENOENT)
                                 return r;
                 }
 
@@ -515,6 +542,18 @@ int manager_save(Manager *m) {
                                 r = set_put_in_addrv(ntp, addresses, r);
                                 if (r < 0)
                                         return r;
+                        } else if (r < 0 && r != -ENOENT)
+                                return r;
+                }
+
+                if (link->network->dhcp_domains) {
+                        const char *domainname;
+
+                        r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
+                        if (r >= 0) {
+                                r = set_put_strdup(domains, domainname);
+                                if (r < 0)
+                                        return r;
                         } else if (r != -ENOENT)
                                 return r;
                 }
@@ -533,33 +572,9 @@ int manager_save(Manager *m) {
                 "# This is private data. Do not parse.\n"
                 "OPER_STATE=%s\n", operstate_str);
 
-        if (!set_isempty(dns)) {
-                bool space = false;
-                char *p;
-
-                fputs("DNS=", f);
-                SET_FOREACH(p, dns, i) {
-                        if (space)
-                                fputc(' ', f);
-                        fputs(p, f);
-                        space = true;
-                }
-                fputc('\n', f);
-        }
-
-        if (!set_isempty(ntp)) {
-                bool space = false;
-                char *p;
-
-                fputs("NTP=", f);
-                SET_FOREACH(p, ntp, i) {
-                        if (space)
-                                fputc(' ', f);
-                        fputs(p, f);
-                        space = true;
-                }
-                fputc('\n', f);
-        }
+        print_string_set(f, "DNS=", dns);
+        print_string_set(f, "NTP=", ntp);
+        print_string_set(f, "DOMAINS=", domains);
 
         r = fflush_and_check(f);
         if (r < 0)
index 9cd7a4a..c5b9614 100644 (file)
@@ -37,6 +37,7 @@ Network.IPv4LL,              config_parse_bool,                  0,
 Network.IPv4LLRoute,         config_parse_bool,                  0,                             offsetof(Network, ipv4ll_route)
 Network.Address,             config_parse_address,               0,                             0
 Network.Gateway,             config_parse_gateway,               0,                             0
+Network.Domains,             config_parse_domains,               0,                             offsetof(Network, domains)
 Network.DNS,                 config_parse_strv,                  0,                             offsetof(Network, dns)
 Network.LLMNR,               config_parse_llmnr,                 0,                             offsetof(Network, llmnr)
 Network.NTP,                 config_parse_strv,                  0,                             offsetof(Network, ntp)
index e13e4a0..803fcdd 100644 (file)
@@ -166,6 +166,7 @@ void network_free(Network *network) {
 
         strv_free(network->ntp);
         strv_free(network->dns);
+        strv_free(network->domains);
 
         netdev_unref(network->bridge);
 
@@ -341,6 +342,47 @@ int config_parse_netdev(const char *unit,
         return 0;
 }
 
+int config_parse_domains(const char *unit,
+                         const char *filename,
+                         unsigned line,
+                         const char *section,
+                         unsigned section_line,
+                         const char *lvalue,
+                         int ltype,
+                         const char *rvalue,
+                         void *data,
+                         void *userdata) {
+        Network *network = userdata;
+        char ***domains = data;
+        char **domain;
+        int r;
+
+        r = config_parse_strv(unit, filename, line, section, section_line,
+                              lvalue, ltype, rvalue, domains, userdata);
+        if (r < 0)
+                return r;
+
+        strv_uniq(*domains);
+        network->wildcard_domain = !!strv_find(*domains, "*");
+
+        STRV_FOREACH(domain, *domains) {
+                if (is_localhost(*domain))
+                        log_syntax(unit, LOG_ERR, filename, line, EINVAL, "'localhost' domain names may not be configured, ignoring assignment: %s", *domain);
+                else if (!hostname_is_valid(*domain)) {
+                        if (!streq(*domain, "*"))
+                                log_syntax(unit, LOG_ERR, filename, line, EINVAL, "domain name is not valid, ignoring assignment: %s", *domain);
+                } else
+                        continue;
+
+                strv_remove(*domains, *domain);
+
+                /* We removed one entry, make sure we don't skip the next one */
+                domain--;
+        }
+
+        return 0;
+}
+
 int config_parse_tunnel(const char *unit,
                         const char *filename,
                         unsigned line,
index 90e798d..c8d89d2 100644 (file)
@@ -111,7 +111,8 @@ struct Network {
         Hashmap *addresses_by_section;
         Hashmap *routes_by_section;
 
-        char **dns, **ntp;
+        bool wildcard_domain;
+        char **domains, **dns, **ntp;
 
         LLMNRSupport llmnr;
 
@@ -224,6 +225,17 @@ int config_parse_netdev(const char *unit, const char *filename, unsigned line,
                         const char *section, unsigned section_line, const char *lvalue,
                         int ltype, const char *rvalue, void *data, void *userdata);
 
+int config_parse_domains(const char *unit,
+                         const char *filename,
+                         unsigned line,
+                         const char *section,
+                         unsigned section_line,
+                         const char *lvalue,
+                         int ltype,
+                         const char *rvalue,
+                         void *data,
+                         void *userdata);
+
 int config_parse_tunnel(const char *unit,
                         const char *filename,
                         unsigned line,
index 85709a4..039a754 100644 (file)
@@ -366,7 +366,10 @@ int dns_scope_llmnr_membership(DnsScope *s, bool b) {
         int fd;
 
         assert(s);
-        assert(s->protocol == DNS_PROTOCOL_LLMNR);
+
+        if (s->protocol != DNS_PROTOCOL_LLMNR)
+                return 0;
+
         assert(s->link);
 
         if (s->family == AF_INET) {
index eb78587..8b3a3ce 100644 (file)
@@ -64,7 +64,7 @@ static int dns_stream_complete(DnsStream *s, int error) {
 static int dns_stream_identify(DnsStream *s) {
         union {
                 struct cmsghdr header; /* For alignment */
-                uint8_t buffer[CMSG_SPACE(MAX(sizeof(struct in_pktinfo), sizeof(struct in6_pktinfo)))
+                uint8_t buffer[CMSG_SPACE(CONST_MAX(sizeof(struct in_pktinfo), sizeof(struct in6_pktinfo)))
                                + EXTRA_CMSG_SPACE /* kernel appears to require extra space */];
         } control;
         struct msghdr mh = {};
index bfbdc7d..04ee204 100644 (file)
@@ -841,7 +841,7 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
         union {
                 struct cmsghdr header; /* For alignment */
-                uint8_t buffer[CMSG_SPACE(MAX(sizeof(struct in_pktinfo), sizeof(struct in6_pktinfo)))
+                uint8_t buffer[CMSG_SPACE(CONST_MAX(sizeof(struct in_pktinfo), sizeof(struct in6_pktinfo)))
                                + CMSG_SPACE(int) /* ttl/hoplimit */
                                + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
         } control;
index 2bac998..b730ac9 100644 (file)
@@ -871,27 +871,47 @@ int log_set_max_level_from_string(const char *e) {
         return 0;
 }
 
+static int parse_proc_cmdline_item(const char *key, const char *value) {
+
+        /*
+         * The systemd.log_xyz= settings are parsed by all tools, and
+         * so is "debug".
+         *
+         * However, "quiet" is only parsed by PID 1!
+         */
+
+        if (streq(key, "debug") && !value)
+                log_set_max_level(LOG_DEBUG);
+
+        else if (streq(key, "systemd.log_target") && value) {
+
+                if (log_set_target_from_string(value) < 0)
+                        log_warning("Failed to parse log target '%s'. Ignoring.", value);
+
+        } else if (streq(key, "systemd.log_level") && value) {
+
+                if (log_set_max_level_from_string(value) < 0)
+                        log_warning("Failed to parse log level '%s'. Ignoring.", value);
+
+        } else if (streq(key, "systemd.log_color") && value) {
+
+                if (log_show_color_from_string(value) < 0)
+                        log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
+
+        } else if (streq(key, "systemd.log_location") && value) {
+
+                if (log_show_location_from_string(value) < 0)
+                        log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
+        }
+
+        return 0;
+}
+
 void log_parse_environment(void) {
         _cleanup_free_ char *line = NULL;
         const char *e;
-        int r;
 
-        r = proc_cmdline(&line);
-        if (r < 0)
-                log_warning("Failed to read /proc/cmdline. Ignoring: %s", strerror(-r));
-        else if (r > 0) {
-                const char *word, *state;
-                size_t l;
-
-                FOREACH_WORD_QUOTED(word, l, line, state) {
-                        if (l == 5 && startswith(word, "debug")) {
-                                log_set_max_level(LOG_DEBUG);
-                                break;
-                        }
-                }
-                if (!isempty(state))
-                        log_warning("Trailing garbage and the end of kernel commandline, ignoring.");
-        }
+        parse_proc_cmdline(parse_proc_cmdline_item);
 
         e = secure_getenv("SYSTEMD_LOG_TARGET");
         if (e && log_set_target_from_string(e) < 0)
index 5619c32..179b24c 100644 (file)
@@ -133,46 +133,55 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
                 })
 
 #undef MAX
-#define MAX(a,b)                                 \
-        __extension__ ({                         \
-                        typeof(a) _a = (a);      \
-                        typeof(b) _b = (b);      \
-                        _a > _b ? _a : _b;       \
+#define MAX(a,b)                                        \
+        __extension__ ({                                \
+                        const typeof(a) _a = (a);       \
+                        const typeof(b) _b = (b);       \
+                        _a > _b ? _a : _b;              \
                 })
 
-#define MAX3(x,y,z)                              \
-        __extension__ ({                         \
-                        typeof(x) _c = MAX(x,y); \
-                        MAX(_c, z);              \
+/* evaluates to (void) if _A or _B are not constant or of different types */
+#define CONST_MAX(_A, _B) \
+        __extension__ (__builtin_choose_expr(                           \
+                __builtin_constant_p(_A) &&                             \
+                __builtin_constant_p(_B) &&                             \
+                __builtin_types_compatible_p(typeof(_A), typeof(_B)),   \
+                ((_A) > (_B)) ? (_A) : (_B),                            \
+                (void)0))
+
+#define MAX3(x,y,z)                                     \
+        __extension__ ({                                \
+                        const typeof(x) _c = MAX(x,y);  \
+                        MAX(_c, z);                     \
                 })
 
 #undef MIN
-#define MIN(a,b)                                \
-        __extension__ ({                        \
-                        typeof(a) _a = (a);     \
-                        typeof(b) _b = (b);     \
-                        _a < _b ? _a : _b;      \
+#define MIN(a,b)                                        \
+        __extension__ ({                                \
+                        const typeof(a) _a = (a);       \
+                        const typeof(b) _b = (b);       \
+                        _a < _b ? _a : _b;              \
                 })
 
-#define MIN3(x,y,z)                              \
-        __extension__ ({                         \
-                        typeof(x) _c = MIN(x,y); \
-                        MIN(_c, z);              \
+#define MIN3(x,y,z)                                     \
+        __extension__ ({                                \
+                        const typeof(x) _c = MIN(x,y);  \
+                        MIN(_c, z);                     \
                 })
 
-#define LESS_BY(A,B)                            \
-        __extension__ ({                        \
-                        typeof(A) _A = (A);     \
-                        typeof(B) _B = (B);     \
-                        _A > _B ? _A - _B : 0;  \
+#define LESS_BY(A,B)                                    \
+        __extension__ ({                                \
+                        const typeof(A) _A = (A);       \
+                        const typeof(B) _B = (B);       \
+                        _A > _B ? _A - _B : 0;          \
                 })
 
 #ifndef CLAMP
 #define CLAMP(x, low, high)                                             \
         __extension__ ({                                                \
-                        typeof(x) _x = (x);                             \
-                        typeof(low) _low = (low);                       \
-                        typeof(high) _high = (high);                    \
+                        const typeof(x) _x = (x);                       \
+                        const typeof(low) _low = (low);                 \
+                        const typeof(high) _high = (high);              \
                         ((_x > _high) ? _high : ((_x < _low) ? _low : _x)); \
                 })
 #endif
index 0db4bd9..18d40f3 100644 (file)
@@ -2084,12 +2084,14 @@ fail:
 }
 
 int release_terminal(void) {
-        int r = 0;
-        struct sigaction sa_old, sa_new = {
+        static const struct sigaction sa_new = {
                 .sa_handler = SIG_IGN,
                 .sa_flags = SA_RESTART,
         };
-        _cleanup_close_ int fd;
+
+        _cleanup_close_ int fd = -1;
+        struct sigaction sa_old;
+        int r = 0;
 
         fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY|O_CLOEXEC);
         if (fd < 0)
@@ -6868,11 +6870,13 @@ char *tempfn_random(const char *p) {
 bool is_localhost(const char *hostname) {
         assert(hostname);
 
-        /* This tries to identify local hostnames described in RFC6761
-         * plus the redhatism of .localdomain */
+        /* This tries to identify local host and domain names
+         * described in RFC6761 plus the redhatism of .localdomain */
 
         return streq(hostname, "localhost") ||
                streq(hostname, "localhost.") ||
+               streq(hostname, "localdomain.") ||
+               streq(hostname, "localdomain") ||
                endswith(hostname, ".localhost") ||
                endswith(hostname, ".localhost.") ||
                endswith(hostname, ".localdomain") ||
@@ -6929,4 +6933,4 @@ int is_symlink(const char *path) {
                 return 1;
 
         return 0;
-}
\ No newline at end of file
+}
index 79566d2..3eedb44 100644 (file)
@@ -282,6 +282,7 @@ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **in
 int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interface, ...) _sd_sentinel_;
 
 int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds);
+int sd_bus_query_sender_privilege(sd_bus_message *call, int capability);
 
 /* Credential handling */
 
index db78507..b2086c7 100644 (file)
@@ -58,11 +58,14 @@ int sd_network_get_operational_state(char **state);
 
 /* Get DNS entries for all links. These are string representations of
  * IP addresses */
-int sd_network_get_dns(char ***addr);
+int sd_network_get_dns(char ***dns);
 
 /* Get NTP entries for all links. These are domain names or string
  * reperesentations of IP addresses */
-int sd_network_get_ntp(char ***addr);
+int sd_network_get_ntp(char ***ntp);
+
+/* Get the search/routing domains for all links. */
+int sd_network_get_domains(char ***domains);
 
 /* Get setup state from ifindex.
  * Possible states:
@@ -107,6 +110,10 @@ int sd_network_link_get_llmnr(int ifindex, char **llmnr);
 /* Get the DNS domain names for a given link. */
 int sd_network_link_get_domains(int ifindex, char ***domains);
 
+/* Returns whether or not domains that don't match any link should be resolved
+ * on this link. 1 for yes, 0 for no and negative value for error */
+int sd_network_link_get_wildcard_domain(int ifindex);
+
 /* Monitor object */
 typedef struct sd_network_monitor sd_network_monitor;
 
index 7d81b0b..a8fa48a 100644 (file)
@@ -70,6 +70,28 @@ static void test_align_power2(void) {
         }
 }
 
+static void test_max(void) {
+        static const struct {
+                int a;
+                int b[CONST_MAX(10, 100)];
+        } val1 = {
+                .a = CONST_MAX(10, 100),
+        };
+        int d = 0;
+
+        assert_cc(sizeof(val1.b) == sizeof(int) * 100);
+
+        /* CONST_MAX returns (void) instead of a value if the passed arguments
+         * are not of the same type or not constant expressions. */
+        assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 10)), int));
+        assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(d, 10)), void));
+        assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 1U)), void));
+
+        assert_se(val1.a == 100);
+        assert_se(MAX(++d, 0) == 1);
+        assert_se(d == 1);
+}
+
 static void test_first_word(void) {
         assert_se(first_word("Hello", ""));
         assert_se(first_word("Hello", "Hello"));
@@ -927,6 +949,7 @@ int main(int argc, char *argv[]) {
 
         test_streq_ptr();
         test_align_power2();
+        test_max();
         test_first_word();
         test_close_many();
         test_parse_boolean();
index 1efbf33..1603695 100644 (file)
@@ -395,7 +395,7 @@ static int method_set_timezone(sd_bus *bus, sd_bus_message *m, void *userdata, s
         if (streq_ptr(z, c->zone))
                 return sd_bus_reply_method_return(m, NULL);
 
-        r = bus_verify_polkit_async(bus, &c->polkit_registry, m, "org.freedesktop.timedate1.set-timezone", interactive, error, method_set_timezone, c);
+        r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_TIME, "org.freedesktop.timedate1.set-timezone", interactive, error, method_set_timezone, c);
         if (r < 0)
                 return r;
         if (r == 0)
@@ -456,7 +456,7 @@ static int method_set_local_rtc(sd_bus *bus, sd_bus_message *m, void *userdata,
         if (lrtc == c->local_rtc)
                 return sd_bus_reply_method_return(m, NULL);
 
-        r = bus_verify_polkit_async(bus, &c->polkit_registry, m, "org.freedesktop.timedate1.set-local-rtc", interactive, error, method_set_local_rtc, c);
+        r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_TIME, "org.freedesktop.timedate1.set-local-rtc", interactive, error, method_set_local_rtc, c);
         if (r < 0)
                 return r;
         if (r == 0)
@@ -561,7 +561,7 @@ static int method_set_time(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bu
         } else
                 timespec_store(&ts, (usec_t) utc);
 
-        r = bus_verify_polkit_async(bus, &c->polkit_registry, m, "org.freedesktop.timedate1.set-time", interactive, error, method_set_time, c);
+        r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_TIME, "org.freedesktop.timedate1.set-time", interactive, error, method_set_time, c);
         if (r < 0)
                 return r;
         if (r == 0)
@@ -601,7 +601,7 @@ static int method_set_ntp(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus
         if ((bool)ntp == c->use_ntp)
                 return sd_bus_reply_method_return(m, NULL);
 
-        r = bus_verify_polkit_async(bus, &c->polkit_registry, m, "org.freedesktop.timedate1.set-ntp", interactive, error, method_set_ntp, c);
+        r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_TIME, "org.freedesktop.timedate1.set-ntp", interactive, error, method_set_ntp, c);
         if (r < 0)
                 return r;
         if (r == 0)