summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO9
-rw-r--r--man/systemd.network.xml13
-rw-r--r--src/core/cgroup.c30
-rw-r--r--src/core/main.c94
-rw-r--r--src/hostname/hostnamectl.c65
-rw-r--r--src/hostname/hostnamed.c12
-rw-r--r--src/kernel-install/90-loaderentry.install9
-rw-r--r--src/libsystemd/sd-bus/bus-convenience.c53
-rw-r--r--src/libsystemd/sd-bus/bus-objects.c25
-rw-r--r--src/libsystemd/sd-bus/bus-util.c24
-rw-r--r--src/libsystemd/sd-bus/bus-util.h4
-rw-r--r--src/libsystemd/sd-network/sd-network.c24
-rw-r--r--src/locale/localed.c7
-rw-r--r--src/login/logind-dbus.c17
-rw-r--r--src/network/networkctl.c19
-rw-r--r--src/network/networkd-link.c35
-rw-r--r--src/network/networkd-manager.c73
-rw-r--r--src/network/networkd-network-gperf.gperf1
-rw-r--r--src/network/networkd-network.c42
-rw-r--r--src/network/networkd.h14
-rw-r--r--src/resolve/resolved-dns-scope.c5
-rw-r--r--src/resolve/resolved-dns-stream.c2
-rw-r--r--src/resolve/resolved-manager.c2
-rw-r--r--src/shared/log.c54
-rw-r--r--src/shared/macro.h61
-rw-r--r--src/shared/util.c16
-rw-r--r--src/systemd/sd-bus.h1
-rw-r--r--src/systemd/sd-network.h11
-rw-r--r--src/test/test-util.c23
-rw-r--r--src/timedate/timedated.c8
30 files changed, 488 insertions, 265 deletions
diff --git a/TODO b/TODO
index 8d3c1caeab..e85eb55672 100644
--- 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
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 290aa6efe5..024509968a 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -301,7 +301,18 @@
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>
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 42bf09f038..9248cb523b 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -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)) {
diff --git a/src/core/main.c b/src/core/main.c
index f33b78d375..792b316c61 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -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();
diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c
index f8e1a811f8..e48736920f 100644
--- a/src/hostname/hostnamectl.c
+++ b/src/hostname/hostnamectl.c
@@ -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;
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index a6f440f4e1..c7f738a62c 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -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)
diff --git a/src/kernel-install/90-loaderentry.install b/src/kernel-install/90-loaderentry.install
index c17b8a98d5..6f032b5a4b 100644
--- a/src/kernel-install/90-loaderentry.install
+++ b/src/kernel-install/90-loaderentry.install
@@ -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
diff --git a/src/libsystemd/sd-bus/bus-convenience.c b/src/libsystemd/sd-bus/bus-convenience.c
index c5b9cd4caa..f88836b884 100644
--- a/src/libsystemd/sd-bus/bus-convenience.c
+++ b/src/libsystemd/sd-bus/bus-convenience.c
@@ -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;
+}
diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c
index dbb04e5ec6..78dab8048d 100644
--- a/src/libsystemd/sd-bus/bus-objects.c
+++ b/src/libsystemd/sd-bus/bus-objects.c
@@ -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);
}
diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c
index 37f5c4620c..65f1d17c9f 100644
--- a/src/libsystemd/sd-bus/bus-util.c
+++ b/src/libsystemd/sd-bus/bus-util.c
@@ -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
diff --git a/src/libsystemd/sd-bus/bus-util.h b/src/libsystemd/sd-bus/bus-util.h
index b3b52af24c..1ac46875b2 100644
--- a/src/libsystemd/sd-bus/bus-util.h
+++ b/src/libsystemd/sd-bus/bus-util.h
@@ -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);
diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c
index 4d8b7e7b2c..3a3f53576f 100644
--- a/src/libsystemd/sd-network/sd-network.c
+++ b/src/libsystemd/sd-network/sd-network.c
@@ -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;
}
diff --git a/src/locale/localed.c b/src/locale/localed.c
index 4d7d02b9a3..5c0bc2c84e 100644
--- a/src/locale/localed.c
+++ b/src/locale/localed.c
@@ -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)
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 1a363c2c59..bcfcba2d07 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -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" :
diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index 33fe8bfc61..6253cbf582 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -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);
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 9eb2e89091..a37561a04a 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -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));
}
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index e3d72edece..f2fe5d5443 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -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)
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 9cd7a4aa61..c5b9614a2b 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -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)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index e13e4a0f62..803fcdd609 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -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,
diff --git a/src/network/networkd.h b/src/network/networkd.h
index 90e798dbf5..c8d89d212b 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -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,
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index 85709a4af8..039a754ff0 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -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) {
diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c
index eb78587ae6..8b3a3ced4b 100644
--- a/src/resolve/resolved-dns-stream.c
+++ b/src/resolve/resolved-dns-stream.c
@@ -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 = {};
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index bfbdc7d55b..04ee204074 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -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;
diff --git a/src/shared/log.c b/src/shared/log.c
index 2bac998bcd..b730ac921a 100644
--- a/src/shared/log.c
+++ b/src/shared/log.c
@@ -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)
diff --git a/src/shared/macro.h b/src/shared/macro.h
index 5619c32e45..179b24c983 100644
--- a/src/shared/macro.h
+++ b/src/shared/macro.h
@@ -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
diff --git a/src/shared/util.c b/src/shared/util.c
index 0db4bd90e8..18d40f398f 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -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
+}
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index 79566d2109..3eedb4450b 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -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 */
diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h
index db785077ff..b2086c7836 100644
--- a/src/systemd/sd-network.h
+++ b/src/systemd/sd-network.h
@@ -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;
diff --git a/src/test/test-util.c b/src/test/test-util.c
index 7d81b0b7be..a8fa48aed2 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -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();
diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index 1efbf3386e..16036953fa 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -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)