]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #15166 from ssahani/networkctl-ipvlan
authorLennart Poettering <lennart@poettering.net>
Tue, 19 May 2020 07:29:45 +0000 (09:29 +0200)
committerGitHub <noreply@github.com>
Tue, 19 May 2020 07:29:45 +0000 (09:29 +0200)
networkctl: Add support to display ipvlan

38 files changed:
TODO
man/kernel-command-line.xml
man/sd_bus_add_object.xml
man/systemd-update-done.service.xml
man/systemd.network.xml
man/systemd.unit.xml
meson.build
src/basic/proc-cmdline.c
src/basic/proc-cmdline.h
src/basic/stat-util.c
src/basic/stat-util.h
src/core/hostname-setup.c
src/core/main.c
src/home/homed.conf
src/hostname/hostnamed.c
src/journal-remote/journal-upload-journal.c
src/libsystemd-network/sd-dhcp6-client.c
src/libsystemd-network/test-dhcp6-client.c
src/libsystemd/sd-bus/bus-objects.c
src/network/netdev/bond.c
src/network/netdev/bond.h
src/network/networkctl.c
src/network/networkd-dhcp-common.c
src/network/networkd-dhcp-common.h
src/network/networkd-dhcp4.c
src/network/networkd-dhcp4.h
src/network/networkd-dhcp6.c
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
src/resolve/resolved-manager.h
src/resolve/resolved-resolv-conf.c
src/shared/bond-util.c [new file with mode: 0644]
src/shared/bond-util.h [new file with mode: 0644]
src/shared/condition.c
src/shared/meson.build
src/systemd/sd-bus-vtable.h
test/fuzz/fuzz-network-parser/directives.network

diff --git a/TODO b/TODO
index 5f0a0004ad7afa16cec5559cd3e89431a8279658..42f2fcfe149536f20f3088cc33ef35abf3870fc7 100644 (file)
--- a/TODO
+++ b/TODO
@@ -22,6 +22,10 @@ Janitorial Clean-ups:
 
 Features:
 
+* add "throttling" to sd-event event sources: optionally, when we wake up too
+  often for one, let's turn it off entirely for a while. Use that for the
+  /proc/self/mountinfo logic.
+
 * move our systemd-user PAM snippet to /usr/, which PAM appears to support
   these days
 
@@ -248,8 +252,7 @@ Features:
   that are linked to these places instead of copied. After all they are
   constant vendor data.
 
-* maybe add kernel cmdline params: 1) to force first-boot mode + 2) to force
-  random seed crediting
+* maybe add kernel cmdline params: to force random seed crediting
 
 * nspawn: on cgroupsv1 issue cgroup empty handler process based on host events,
   so that we make cgroup agent logic safe
@@ -511,9 +514,6 @@ Features:
 
 * support projid-based quota in machinectl for containers
 
-* maybe use SOURCE_DATE_EPOCH (i.e. the env var the reproducible builds folks
-  introduced) as the RTC epoch, instead of the mtime of NEWS.
-
 * add a way to lock down cgroup migration: a boolean, which when set for a unit
   makes sure the processes in it can never migrate out of it
 
index 4aac14ea180c8bf39961b3dc231ea6606888350b..0f2972a0b6840346228a56198f3e8d6b8d85eddc 100644 (file)
 
         <listitem><para>Takes a boolean argument, defaults to on. If off,
         <citerefentry><refentrytitle>systemd-firstboot.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-        will not query the user for basic system settings, even if the system boots up for the first time and the
-        relevant settings are not initialized yet.</para></listitem>
+        will not query the user for basic system settings, even if the system boots up for the first time and
+        the relevant settings are not initialized yet. Not to be confused with
+        <varname>systemd.condition-first-boot=</varname> (see below), which overrides the result of the
+        <varname>ConditionFirstBoot=</varname> unit file condition, and thus controls more than just
+        <filename>systemd-firstboot.service</filename> behaviour.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>systemd.condition-needs-update=</varname></term>
+
+        <listitem><para>Takes a boolean argument. If specified, overrides the result of
+        <varname>ConditionNeedsUpdate=</varname> unit condition checks. See
+        <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
+        details.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>systemd.condition-first-boot=</varname></term>
+
+        <listitem><para>Takes a boolean argument. If specified, overrides the result of
+        <varname>ConditionFirstBoot=</varname> unit condition checks. See
+        <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
+        details. Not to be confused with <varname>systemd.firstboot=</varname> which only controls behaviour
+        of the <filename>systemd-firstboot.service</filename> system service but has no effect on the
+        condition check (see above).</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>systemd.clock-usec=</varname></term>
+
+        <listitem><para>Takes a decimal, numeric timestamp in µs since January 1st 1970, 00:00am, to set the
+        system clock to. The system time is set to the specified timestamp early during
+        boot. It is not propagated to the hardware clock (RTC).</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>systemd.hostname=</varname></term>
+
+        <listitem><para>Accepts a hostname to set during early boot. If specified takes precedence over what
+        is set in <filename>/etc/hostname</filename>. Note that this does not bar later runtime changes to
+        the hostname, it simply controls the initial hostname set during early boot.</para></listitem>
       </varlistentry>
     </variablelist>
 
index 60f04187f8c05f41df685359d2a45ea27a5e7ed7..102ee66d297aecf6cf6302675b53e149a36dda5c 100644 (file)
           This corresponds to the <constant>org.freedesktop.systemd1.Explicit</constant> annotation
           in introspection data.</para></listitem>
         </varlistentry>
+
+        <varlistentry>
+          <term><constant>SD_BUS_VTABLE_SENSITIVE</constant></term>
+
+          <listitem><para>Mark this vtable method entry as processing sensitive data. When set,
+          incoming method call messages and their outgoing reply messages are marked as sensitive using
+          <citerefentry><refentrytitle>sd_bus_message_sensitive</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+          so that they are erased from memory when freed.</para></listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><constant>SD_BUS_VTABLE_ABSOLUTE_OFFSET</constant></term>
+
+          <listitem><para>Mark this vtable method or property entry so that the user data pointer passed to
+          its associated handler functions is determined slightly differently: instead of adding the offset
+          parameter of the entry to the user data pointer specified during vtable registration, the offset is
+          passed directly, converted to a pointer, without taking the user data pointer specified during
+          vtable registration into account.</para></listitem>
+        </varlistentry>
       </variablelist>
     </refsect2>
   </refsect1>
index ad412691a946847c39d1ae09cc501969aed5d3be..91196dff301fb92ce9cab3b2a82ac8a627b82495 100644 (file)
     <citerefentry project='man-pages'><refentrytitle>touch</refentrytitle><manvolnum>1</manvolnum></citerefentry>
     on it.</para>
 
+    <para>Note that if the <varname>systemd.condition-needs-update=</varname> kernel command line option is
+    used it overrides the <varname>ConditionNeedsUpdate=</varname> unit condition checks. In that case
+    <filename>systemd-update-done.service</filename> will not reset the condition state until a follow-up
+    reboot where the kernel switch is not specified anymore.</para>
   </refsect1>
 
   <refsect1>
index d891873c7eb193580d966f9ebf475041940c4e1a..e6d005400bc2f5defa3c117b2810c00800f2e9d7 100644 (file)
         <varlistentry>
           <term><varname>RequestOptions=</varname></term>
           <listitem>
-            <para>A whitespace-separated list of integers in the range 1–254.</para>
+            <para>When configured, allows to set arbitrary request options in the DHCPv4 request options list and will be
+            sent to the DHCPV4 server. A whitespace-separated list of integers in the range 1..254. Defaults to unset.</para>
           </listitem>
         </varlistentry>
 
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><varname>RequestOptions=</varname></term>
+          <listitem>
+            <para>When configured, allows to set arbitrary request options in the DHCPv6 request options list and will
+            sent to the DHCPV6 server. A whitespace-separated list of integers in the range 1..254. Defaults to unset.</para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term><varname>ForceDHCPv6PDOtherInformation=</varname></term>
           <listitem>
           <listitem>
             <para>Takes an IPv6 address with prefix length as <varname>Address=</varname> in
             the "[Network]" section. Specifies the DHCPv6 client for the requesting router to include
-            a prefix-hint in the DHCPv6 solicitation. Prefix ranges 1-128. Defaults to unset.</para>
+            a prefix-hint in the DHCPv6 solicitation. Prefix ranges 1..128. Defaults to unset.</para>
           </listitem>
         </varlistentry>
 
index b91c1ad0ecca64919166fbe93562f9befdaa23cc..fa8ed1b47bbeb89d113bdbb8779f4b269b9371e9 100644 (file)
           <citerefentry><refentrytitle>systemd-update-done.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
           to make sure they run before the stamp file's modification time gets reset indicating a completed
           update.</para>
+
+          <para>If the <varname>systemd.condition-needs-update=</varname> option is specified on the kernel
+          command line (taking a boolean), it will override the result of this condition check, taking
+          precedence over any file modification time checks. If it is used
+          <filename>systemd-update-done.service</filename> will not have immediate effect on any following
+          <varname>ConditionNeedsUpdate=</varname> checks, until the system is rebooted where the kernel
+          command line option is not specified anymore.</para>
           </listitem>
         </varlistentry>
 
           (specifically: an <filename>/etc</filename> with no <filename>/etc/machine-id</filename>). This may
           be used to populate <filename>/etc</filename> on the first boot after factory reset, or when a new
           system instance boots up for the first time.</para>
+
+          <para>If the <varname>systemd.condition-first-boot=</varname> option is specified on the kernel
+          command line (taking a boolean), it will override the result of this condition check, taking
+          precedence over <filename>/etc/machine-id</filename> existence checks.</para>
           </listitem>
         </varlistentry>
 
index 580d5126fae71178165da41d0264a664b06203c8..e9eb7f9569eb3d502aeeb7fe116f01d0418fe051 100644 (file)
@@ -669,8 +669,13 @@ conf.set_quoted('DEFAULT_NET_NAMING_SCHEME', default_net_naming_scheme)
 
 time_epoch = get_option('time-epoch')
 if time_epoch == -1
-        NEWS = files('NEWS')
-        time_epoch = run_command(stat, '-c', '%Y', NEWS).stdout().to_int()
+        source_date_epoch = run_command('sh', ['-c', 'echo "$SOURCE_DATE_EPOCH"']).stdout().strip()
+        if source_date_epoch != ''
+                time_epoch = source_date_epoch.to_int()
+        else
+                NEWS = files('NEWS')
+                time_epoch = run_command(stat, '-c', '%Y', NEWS).stdout().to_int()
+        endif
 endif
 conf.set('TIME_EPOCH', time_epoch)
 
index d3d99d9a7f90228222eaa09de6b778a048b8a95c..d8d30b0f1df44a93c3572a2fc80ee385fe8a7f80 100644 (file)
@@ -268,17 +268,17 @@ int proc_cmdline_get_bool(const char *key, bool *ret) {
         r = proc_cmdline_get_key(key, PROC_CMDLINE_VALUE_OPTIONAL, &v);
         if (r < 0)
                 return r;
-        if (r == 0) {
+        if (r == 0) { /* key not specified at all */
                 *ret = false;
                 return 0;
         }
 
-        if (v) { /* parameter passed */
+        if (v) { /* key with parameter passed */
                 r = parse_boolean(v);
                 if (r < 0)
                         return r;
                 *ret = r;
-        } else /* no parameter passed */
+        } else /* key without parameter passed */
                 *ret = true;
 
         return 1;
index 4115fdbc99fd7d00dbfc33b19681d16d54efcac6..275f46c89ec22987ec77eff2beb182de60683c0b 100644 (file)
@@ -6,9 +6,9 @@
 #include "log.h"
 
 typedef enum ProcCmdlineFlags {
-        PROC_CMDLINE_STRIP_RD_PREFIX = 1 << 0,
-        PROC_CMDLINE_VALUE_OPTIONAL  = 1 << 1,
-        PROC_CMDLINE_RD_STRICT       = 1 << 2,
+        PROC_CMDLINE_STRIP_RD_PREFIX = 1 << 0, /* automatically strip "rd." prefix if it is set (and we are in the initrd, since otherwise we'd not consider it anyway) */
+        PROC_CMDLINE_VALUE_OPTIONAL  = 1 << 1, /* the value is optional (for boolean switches that can omit the value) */
+        PROC_CMDLINE_RD_STRICT       = 1 << 2, /* ignore this in the initrd */
 } ProcCmdlineFlags;
 
 typedef int (*proc_cmdline_parse_t)(const char *key, const char *value, void *data);
index 1f3de56cf926781ba94da9682c98d3d516150710..e4e4d8f0762108bedb3e8f863acb1d8887d33e7f 100644 (file)
@@ -388,3 +388,24 @@ int proc_mounted(void) {
 
         return r;
 }
+
+bool stat_inode_unmodified(const struct stat *a, const struct stat *b) {
+
+        /* Returns if the specified stat structures reference the same, unmodified inode. This check tries to
+         * be reasonably careful when detecting changes: we check both inode and mtime, to cater for file
+         * systems where mtimes are fixed to 0 (think: ostree/nixos type installations). We also check file
+         * size, backing device, inode type and if this refers to a device not the major/minor.
+         *
+         * Note that we don't care if file attributes such as ownership or access mode change, this here is
+         * about contents of the file. The purpose here is to detect file contents changes, and nothing
+         * else. */
+
+        return a && b &&
+                (a->st_mode & S_IFMT) != 0 && /* We use the check for .st_mode if the structure was ever initialized */
+                ((a->st_mode ^ b->st_mode) & S_IFMT) == 0 &&  /* same inode type */
+                a->st_mtime == b->st_mtime &&
+                (!S_ISREG(a->st_mode) || a->st_size == b->st_size) && /* if regular file, compare file size */
+                a->st_dev == b->st_dev &&
+                a->st_ino == b->st_ino &&
+                (!(S_ISCHR(a->st_mode) || S_ISBLK(a->st_mode)) || a->st_rdev == b->st_rdev); /* if device node, also compare major/minor, because we can */
+}
index 81607483121d66839bd93346d88a6fc05f203c5a..59aedcb7c4d727bfa1ecce990e6148c3c6cb21be 100644 (file)
@@ -89,3 +89,5 @@ int device_path_make_canonical(mode_t mode, dev_t devno, char **ret);
 int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devno);
 
 int proc_mounted(void);
+
+bool stat_inode_unmodified(const struct stat *a, const struct stat *b);
index 83cce88131eb656396c2ef86216060ce600b68db..6d047db8388c8e94b3947f75e8c1a4fac35e6ba1 100644 (file)
 #include "hostname-util.h"
 #include "log.h"
 #include "macro.h"
+#include "proc-cmdline.h"
 #include "string-util.h"
 #include "util.h"
 
 int hostname_setup(void) {
         _cleanup_free_ char *b = NULL;
+        const char *hn = NULL;
         bool enoent = false;
-        const char *hn;
         int r;
 
-        r = read_etc_hostname(NULL, &b);
-        if (r < 0) {
-                if (r == -ENOENT)
-                        enoent = true;
-                else
-                        log_warning_errno(r, "Failed to read configured hostname: %m");
+        r = proc_cmdline_get_key("systemd.hostname", 0, &b);
+        if (r < 0)
+                log_warning_errno(r, "Failed to retrieve system hostname from kernel command line, ignoring: %m");
+        else if (r > 0) {
+                if (hostname_is_valid(b, true))
+                        hn = b;
+                else  {
+                        log_warning("Hostname specified on kernel command line is invalid, ignoring: %s", b);
+                        b = mfree(b);
+                }
+        }
 
-                hn = NULL;
-        } else
-                hn = b;
+        if (!hn) {
+                r = read_etc_hostname(NULL, &b);
+                if (r < 0) {
+                        if (r == -ENOENT)
+                                enoent = true;
+                        else
+                                log_warning_errno(r, "Failed to read configured hostname: %m");
+                } else
+                        hn = b;
+        }
 
         if (isempty(hn)) {
-                /* Don't override the hostname if it is already set
-                 * and not explicitly configured */
+                /* Don't override the hostname if it is already set and not explicitly configured */
                 if (hostname_is_set())
                         return 0;
 
index c9eaf70bd6c84d7eb231a305892f8bea4c04eba1..3ab4aa4e1988eab923339fd128005178db7973c9 100644 (file)
@@ -146,6 +146,7 @@ static EmergencyAction arg_cad_burst_action;
 static OOMPolicy arg_default_oom_policy;
 static CPUSet arg_cpu_affinity;
 static NUMAPolicy arg_numa_policy;
+static usec_t arg_clock_usec;
 
 /* A copy of the original environment block */
 static char **saved_env = NULL;
@@ -491,6 +492,15 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
 
                 (void) parse_path_argument_and_warn(value, false, &arg_watchdog_device);
 
+        } else if (proc_cmdline_key_streq(key, "systemd.clock_usec")) {
+
+                if (proc_cmdline_value_missing(key, value))
+                        return 0;
+
+                r = safe_atou64(value, &arg_clock_usec);
+                if (r < 0)
+                        log_warning_errno(r, "Failed to parse systemd.clock_usec= argument, ignoring: %s", value);
+
         } else if (streq(key, "quiet") && !value) {
 
                 if (arg_show_status == _SHOW_STATUS_INVALID)
@@ -1504,6 +1514,9 @@ static int become_shutdown(
 static void initialize_clock(void) {
         int r;
 
+        /* This is called very early on, before we parse the kernel command line or otherwise figure out why
+         * we are running, but only once. */
+
         if (clock_is_localtime(NULL) > 0) {
                 int min;
 
@@ -1542,6 +1555,25 @@ static void initialize_clock(void) {
                 log_info("System time before build time, advancing clock.");
 }
 
+static void apply_clock_update(void) {
+        struct timespec ts;
+
+        /* This is called later than initialize_clock(), i.e. after we parsed configuration files/kernel
+         * command line and such. */
+
+        if (arg_clock_usec == 0)
+                return;
+
+        if (clock_settime(CLOCK_REALTIME, timespec_store(&ts, arg_clock_usec)) < 0)
+                log_error_errno(errno, "Failed to set system clock to time specified on kernel command line: %m");
+        else {
+                char buf[FORMAT_TIMESTAMP_MAX];
+
+                log_info("Set system clock to %s, as specified on the kernel command line.",
+                         format_timestamp(buf, sizeof(buf), arg_clock_usec));
+        }
+}
+
 static void initialize_coredump(bool skip_setup) {
 #if ENABLE_COREDUMP
         if (getpid_cached() != 1)
@@ -2658,6 +2690,8 @@ int main(int argc, char *argv[]) {
         assert_se(chdir("/") == 0);
 
         if (arg_action == ACTION_RUN) {
+                /* Apply the systemd.clock_usec= kernel command line switch */
+                apply_clock_update();
 
                 /* A core pattern might have been specified via the cmdline.  */
                 initialize_core_pattern(skip_setup);
index a8a48fe5939b80b4b29934d23c1b189920d12813..6de75fc5ca297c773973a9e702f6cf6760caca33 100644 (file)
@@ -11,6 +11,6 @@
 #
 # See homed.conf(5) for details
 
-[Resolve]
+[Home]
 #DefaultStorage=
 #DefaultFileSystemType=ext4
index 701041c12adbcf16be7e47832d6e6c9c974b35f7..e694a95a0411327e422b3001904f2f59c0904356 100644 (file)
@@ -43,9 +43,6 @@ enum {
         PROP_CHASSIS,
         PROP_DEPLOYMENT,
         PROP_LOCATION,
-        PROP_KERNEL_NAME,
-        PROP_KERNEL_RELEASE,
-        PROP_KERNEL_VERSION,
         PROP_OS_PRETTY_NAME,
         PROP_OS_CPE_NAME,
         PROP_HOME_URL,
@@ -55,8 +52,6 @@ enum {
 typedef struct Context {
         char *data[_PROP_MAX];
         Hashmap *polkit_registry;
-        sd_id128_t uuid;
-        bool has_uuid;
 } Context;
 
 static void context_reset(Context *c) {
@@ -68,7 +63,7 @@ static void context_reset(Context *c) {
                 c->data[p] = mfree(c->data[p]);
 }
 
-static void context_clear(Context *c) {
+static void context_destroy(Context *c) {
         assert(c);
 
         context_reset(c);
@@ -77,20 +72,11 @@ static void context_clear(Context *c) {
 
 static int context_read_data(Context *c) {
         int r;
-        struct utsname u;
 
         assert(c);
 
         context_reset(c);
 
-        assert_se(uname(&u) >= 0);
-        c->data[PROP_KERNEL_NAME] = strdup(u.sysname);
-        c->data[PROP_KERNEL_RELEASE] = strdup(u.release);
-        c->data[PROP_KERNEL_VERSION] = strdup(u.version);
-        if (!c->data[PROP_KERNEL_NAME] || !c->data[PROP_KERNEL_RELEASE] ||
-            !c->data[PROP_KERNEL_VERSION])
-                return -ENOMEM;
-
         c->data[PROP_HOSTNAME] = gethostname_malloc();
         if (!c->data[PROP_HOSTNAME])
                 return -ENOMEM;
@@ -116,17 +102,6 @@ static int context_read_data(Context *c) {
         if (r < 0 && r != -ENOENT)
                 return r;
 
-        r = id128_read("/sys/class/dmi/id/product_uuid", ID128_UUID, &c->uuid);
-        if (r == -ENOENT)
-                r = id128_read("/sys/firmware/devicetree/base/vm,uuid", ID128_UUID, &c->uuid);
-        if (r < 0)
-                log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
-                               "Failed to read product UUID, ignoring: %m");
-        else if (sd_id128_is_null(c->uuid) || sd_id128_is_allf(c->uuid))
-                log_debug("DMI product UUID " SD_ID128_FORMAT_STR " is all 0x00 or all 0xFF, ignoring.", SD_ID128_FORMAT_VAL(c->uuid));
-        else
-                c->has_uuid = true;
-
         return 0;
 }
 
@@ -411,6 +386,22 @@ static int property_get_chassis(
         return sd_bus_message_append(reply, "s", name);
 }
 
+static int property_get_uname_field(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        struct utsname u;
+
+        assert_se(uname(&u) >= 0);
+
+        return sd_bus_message_append(reply, "s", (char*) &u + PTR_TO_SIZE(userdata));
+}
+
 static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *error) {
         Context *c = userdata;
         const char *name;
@@ -627,13 +618,27 @@ static int method_set_location(sd_bus_message *m, void *userdata, sd_bus_error *
 static int method_get_product_uuid(sd_bus_message *m, void *userdata, sd_bus_error *error) {
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         Context *c = userdata;
+        bool has_uuid = false;
         int interactive, r;
+        sd_id128_t uuid;
 
         assert(m);
         assert(c);
 
-        if (!c->has_uuid)
-                return sd_bus_error_set(error, BUS_ERROR_NO_PRODUCT_UUID, "Failed to read product UUID from /sys/class/dmi/id/product_uuid");
+        r = id128_read("/sys/class/dmi/id/product_uuid", ID128_UUID, &uuid);
+        if (r == -ENOENT)
+                r = id128_read("/sys/firmware/devicetree/base/vm,uuid", ID128_UUID, &uuid);
+        if (r < 0)
+                log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
+                               "Failed to read product UUID, ignoring: %m");
+        else if (sd_id128_is_null(uuid) || sd_id128_is_allf(uuid))
+                log_debug("DMI product UUID " SD_ID128_FORMAT_STR " is all 0x00 or all 0xFF, ignoring.", SD_ID128_FORMAT_VAL(uuid));
+        else
+                has_uuid = true;
+
+        if (!has_uuid)
+                return sd_bus_error_set(error, BUS_ERROR_NO_PRODUCT_UUID,
+                                        "Failed to read product UUID from firmware.");
 
         r = sd_bus_message_read(m, "b", &interactive);
         if (r < 0)
@@ -657,7 +662,7 @@ static int method_get_product_uuid(sd_bus_message *m, void *userdata, sd_bus_err
         if (r < 0)
                 return r;
 
-        r = sd_bus_message_append_array(reply, 'y', &c->uuid, sizeof(c->uuid));
+        r = sd_bus_message_append_array(reply, 'y', &uuid, sizeof(uuid));
         if (r < 0)
                 return r;
 
@@ -673,9 +678,9 @@ static const sd_bus_vtable hostname_vtable[] = {
         SD_BUS_PROPERTY("Chassis", "s", property_get_chassis, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("Deployment", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_DEPLOYMENT, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("Location", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_LOCATION, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
-        SD_BUS_PROPERTY("KernelName", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_KERNEL_NAME, SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("KernelRelease", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_KERNEL_RELEASE, SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("KernelVersion", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_KERNEL_VERSION, SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("KernelName", "s", property_get_uname_field, offsetof(struct utsname, sysname), SD_BUS_VTABLE_ABSOLUTE_OFFSET|SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("KernelRelease", "s", property_get_uname_field, offsetof(struct utsname, release), SD_BUS_VTABLE_ABSOLUTE_OFFSET|SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("KernelVersion", "s", property_get_uname_field, offsetof(struct utsname, version), SD_BUS_VTABLE_ABSOLUTE_OFFSET|SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("OperatingSystemPrettyName", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_OS_PRETTY_NAME, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("OperatingSystemCPEName", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_OS_CPE_NAME, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("HomeURL", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_HOME_URL, SD_BUS_VTABLE_PROPERTY_CONST),
@@ -780,7 +785,7 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
 }
 
 static int run(int argc, char *argv[]) {
-        _cleanup_(context_clear) Context context = {};
+        _cleanup_(context_destroy) Context context = {};
         _cleanup_(sd_event_unrefp) sd_event *event = NULL;
         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
index 5bfe5acadcebc54159089ff342c84597c5feb4d5..da37b3416ff4ce1b4bee2daf122cfc8b9e5f3819 100644 (file)
@@ -410,5 +410,5 @@ int open_journal_for_upload(Uploader *u,
                                                cursor);
         }
 
-        return process_journal_input(u, 1 + !!after_cursor);
+        return process_journal_input(u, !!after_cursor);
 }
index 08b4c77d9017babf1762f9cf80a7f2f1b32af1c0..51716c28bb604edd4f4e25513cc839a15e7f48d9 100644 (file)
@@ -253,7 +253,8 @@ static int dhcp6_client_set_duid_internal(
                         r = dhcp_validate_duid_len(duid_type, duid_len, false);
                         if (r < 0)
                                 return log_dhcp6_client_errno(client, r, "Failed to validate length of DUID: %m");
-                        log_dhcp6_client(client, "Setting DUID of type %u with unexpected content", duid_type);
+
+                        log_dhcp6_client(client, "Using DUID of type %u of incorrect length, proceeding.", duid_type);
                 }
 
                 client->duid.type = htobe16(duid_type);
@@ -357,18 +358,8 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option)
         assert_return(client, -EINVAL);
         assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
 
-        switch(option) {
-
-        case SD_DHCP6_OPTION_DNS_SERVERS:
-        case SD_DHCP6_OPTION_DOMAIN_LIST:
-        case SD_DHCP6_OPTION_SNTP_SERVERS:
-        case SD_DHCP6_OPTION_NTP_SERVER:
-        case SD_DHCP6_OPTION_RAPID_COMMIT:
-                break;
-
-        default:
+        if (option <= 0 || option >= 255)
                 return -EINVAL;
-        }
 
         for (t = 0; t < client->req_opts_len; t++)
                 if (client->req_opts[t] == htobe16(option))
index 4b89b320b756cf67d06f4bb9aa5408b576db3aae..3a68f1fe718619e7011c5e8a79df41b3e0a36599 100644 (file)
@@ -61,12 +61,12 @@ static int test_client_basic(sd_event *e) {
         assert_se(sd_dhcp6_client_set_fqdn(client, "~host") == -EINVAL);
         assert_se(sd_dhcp6_client_set_fqdn(client, "~host.domain") == -EINVAL);
 
-        assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_CLIENTID) == -EINVAL);
+        assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_CLIENTID) == 0);
         assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVERS) == -EEXIST);
         assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NTP_SERVER) == -EEXIST);
         assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SNTP_SERVERS) == -EEXIST);
         assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN_LIST) == -EEXIST);
-        assert_se(sd_dhcp6_client_set_request_option(client, 10) == -EINVAL);
+        assert_se(sd_dhcp6_client_set_request_option(client, 10) == 0);
 
         assert_se(sd_dhcp6_client_set_information_request(client, 1) >= 0);
         v = 0;
index ad66d634d7ebfd1c03fb7f40b4bbd2250af97f68..6abac8822c6eed5792529f5ca7cb09b67af58f7d 100644 (file)
@@ -56,7 +56,7 @@ static int node_vtable_get_userdata(
 static void *vtable_method_convert_userdata(const sd_bus_vtable *p, void *u) {
         assert(p);
 
-        if (!u)
+        if (!u || FLAGS_SET(p->flags, SD_BUS_VTABLE_ABSOLUTE_OFFSET))
                 return SIZE_TO_PTR(p->x.method.offset); /* don't add offset on NULL, to make ubsan happy */
 
         return (uint8_t*) u + p->x.method.offset;
@@ -65,7 +65,7 @@ static void *vtable_method_convert_userdata(const sd_bus_vtable *p, void *u) {
 static void *vtable_property_convert_userdata(const sd_bus_vtable *p, void *u) {
         assert(p);
 
-        if (!u)
+        if (!u || FLAGS_SET(p->flags, SD_BUS_VTABLE_ABSOLUTE_OFFSET))
                 return SIZE_TO_PTR(p->x.property.offset); /* as above */
 
         return (uint8_t*) u + p->x.property.offset;
index 8df39e35843f625af265483a35811bdf014a8bae..23bd3e1e46476451e8110dd17f70a797ebebedde 100644 (file)
@@ -2,13 +2,13 @@
 
 #include "alloc-util.h"
 #include "bond.h"
+#include "bond-util.h"
 #include "conf-parser.h"
 #include "ether-addr-util.h"
 #include "extract-word.h"
 #include "netlink-util.h"
 #include "networkd-manager.h"
 #include "string-table.h"
-#include "string-util.h"
 
 /*
  * Number of seconds between instances where the bonding
 #define GRATUITOUS_ARP_MAX        255
 #define GRATUITOUS_ARP_DEFAULT    1
 
-static const char* const bond_mode_table[_NETDEV_BOND_MODE_MAX] = {
-        [NETDEV_BOND_MODE_BALANCE_RR] = "balance-rr",
-        [NETDEV_BOND_MODE_ACTIVE_BACKUP] = "active-backup",
-        [NETDEV_BOND_MODE_BALANCE_XOR] = "balance-xor",
-        [NETDEV_BOND_MODE_BROADCAST] = "broadcast",
-        [NETDEV_BOND_MODE_802_3AD] = "802.3ad",
-        [NETDEV_BOND_MODE_BALANCE_TLB] = "balance-tlb",
-        [NETDEV_BOND_MODE_BALANCE_ALB] = "balance-alb",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(bond_mode, BondMode);
 DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_mode, bond_mode, BondMode, "Failed to parse bond mode");
-
-static const char* const bond_xmit_hash_policy_table[_NETDEV_BOND_XMIT_HASH_POLICY_MAX] = {
-        [NETDEV_BOND_XMIT_HASH_POLICY_LAYER2] = "layer2",
-        [NETDEV_BOND_XMIT_HASH_POLICY_LAYER34] = "layer3+4",
-        [NETDEV_BOND_XMIT_HASH_POLICY_LAYER23] = "layer2+3",
-        [NETDEV_BOND_XMIT_HASH_POLICY_ENCAP23] = "encap2+3",
-        [NETDEV_BOND_XMIT_HASH_POLICY_ENCAP34] = "encap3+4",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(bond_xmit_hash_policy, BondXmitHashPolicy);
 DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_xmit_hash_policy,
                          bond_xmit_hash_policy,
                          BondXmitHashPolicy,
-                         "Failed to parse bond transmit hash policy")
-
-static const char* const bond_lacp_rate_table[_NETDEV_BOND_LACP_RATE_MAX] = {
-        [NETDEV_BOND_LACP_RATE_SLOW] = "slow",
-        [NETDEV_BOND_LACP_RATE_FAST] = "fast",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(bond_lacp_rate, BondLacpRate);
-DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_lacp_rate, bond_lacp_rate, BondLacpRate, "Failed to parse bond lacp rate")
-
-static const char* const bond_ad_select_table[_NETDEV_BOND_AD_SELECT_MAX] = {
-        [NETDEV_BOND_AD_SELECT_STABLE] = "stable",
-        [NETDEV_BOND_AD_SELECT_BANDWIDTH] = "bandwidth",
-        [NETDEV_BOND_AD_SELECT_COUNT] = "count",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(bond_ad_select, BondAdSelect);
+                         "Failed to parse bond transmit hash policy");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_lacp_rate, bond_lacp_rate, BondLacpRate, "Failed to parse bond lacp rate");
 DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_ad_select, bond_ad_select, BondAdSelect, "Failed to parse bond AD select");
-
-static const char* const bond_fail_over_mac_table[_NETDEV_BOND_FAIL_OVER_MAC_MAX] = {
-        [NETDEV_BOND_FAIL_OVER_MAC_NONE] = "none",
-        [NETDEV_BOND_FAIL_OVER_MAC_ACTIVE] = "active",
-        [NETDEV_BOND_FAIL_OVER_MAC_FOLLOW] = "follow",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(bond_fail_over_mac, BondFailOverMac);
 DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_fail_over_mac, bond_fail_over_mac, BondFailOverMac, "Failed to parse bond fail over MAC");
-
-static const char *const bond_arp_validate_table[_NETDEV_BOND_ARP_VALIDATE_MAX] = {
-        [NETDEV_BOND_ARP_VALIDATE_NONE] = "none",
-        [NETDEV_BOND_ARP_VALIDATE_ACTIVE]= "active",
-        [NETDEV_BOND_ARP_VALIDATE_BACKUP]= "backup",
-        [NETDEV_BOND_ARP_VALIDATE_ALL]= "all",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(bond_arp_validate, BondArpValidate);
 DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_arp_validate, bond_arp_validate, BondArpValidate, "Failed to parse bond arp validate");
-
-static const char *const bond_arp_all_targets_table[_NETDEV_BOND_ARP_ALL_TARGETS_MAX] = {
-        [NETDEV_BOND_ARP_ALL_TARGETS_ANY] = "any",
-        [NETDEV_BOND_ARP_ALL_TARGETS_ALL] = "all",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(bond_arp_all_targets, BondArpAllTargets);
 DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_arp_all_targets, bond_arp_all_targets, BondArpAllTargets, "Failed to parse bond Arp all targets");
-
-static const char *const bond_primary_reselect_table[_NETDEV_BOND_PRIMARY_RESELECT_MAX] = {
-        [NETDEV_BOND_PRIMARY_RESELECT_ALWAYS] = "always",
-        [NETDEV_BOND_PRIMARY_RESELECT_BETTER]= "better",
-        [NETDEV_BOND_PRIMARY_RESELECT_FAILURE]= "failure",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(bond_primary_reselect, BondPrimaryReselect);
 DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_primary_reselect, bond_primary_reselect, BondPrimaryReselect, "Failed to parse bond primary reselect");
 
 static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
index 28796a3a8be1d40ff75893c64c4a2b9442830b49..64b2dd04a2bc56e27e381e29022a08c0564ef673 100644 (file)
@@ -4,85 +4,11 @@
 #include <netinet/in.h>
 #include <linux/if_bonding.h>
 
-#include "in-addr-util.h"
+#include "bond-util.h"
+#include "macro.h"
 #include "netdev.h"
 #include "ordered-set.h"
 
-/*
- * Maximum number of targets supported by the kernel for a single
- * bond netdev.
- */
-#define NETDEV_BOND_ARP_TARGETS_MAX 16
-
-typedef enum BondMode {
-        NETDEV_BOND_MODE_BALANCE_RR    = BOND_MODE_ROUNDROBIN,
-        NETDEV_BOND_MODE_ACTIVE_BACKUP = BOND_MODE_ACTIVEBACKUP,
-        NETDEV_BOND_MODE_BALANCE_XOR   = BOND_MODE_XOR,
-        NETDEV_BOND_MODE_BROADCAST     = BOND_MODE_BROADCAST,
-        NETDEV_BOND_MODE_802_3AD       = BOND_MODE_8023AD,
-        NETDEV_BOND_MODE_BALANCE_TLB   = BOND_MODE_TLB,
-        NETDEV_BOND_MODE_BALANCE_ALB   = BOND_MODE_ALB,
-        _NETDEV_BOND_MODE_MAX,
-        _NETDEV_BOND_MODE_INVALID      = -1
-} BondMode;
-
-typedef enum BondXmitHashPolicy {
-        NETDEV_BOND_XMIT_HASH_POLICY_LAYER2   = BOND_XMIT_POLICY_LAYER2,
-        NETDEV_BOND_XMIT_HASH_POLICY_LAYER34  = BOND_XMIT_POLICY_LAYER34,
-        NETDEV_BOND_XMIT_HASH_POLICY_LAYER23  = BOND_XMIT_POLICY_LAYER23,
-        NETDEV_BOND_XMIT_HASH_POLICY_ENCAP23  = BOND_XMIT_POLICY_ENCAP23,
-        NETDEV_BOND_XMIT_HASH_POLICY_ENCAP34  = BOND_XMIT_POLICY_ENCAP34,
-        _NETDEV_BOND_XMIT_HASH_POLICY_MAX,
-        _NETDEV_BOND_XMIT_HASH_POLICY_INVALID = -1
-} BondXmitHashPolicy;
-
-typedef enum BondLacpRate {
-        NETDEV_BOND_LACP_RATE_SLOW,
-        NETDEV_BOND_LACP_RATE_FAST,
-        _NETDEV_BOND_LACP_RATE_MAX,
-        _NETDEV_BOND_LACP_RATE_INVALID = -1,
-} BondLacpRate;
-
-typedef enum BondAdSelect {
-        NETDEV_BOND_AD_SELECT_STABLE,
-        NETDEV_BOND_AD_SELECT_BANDWIDTH,
-        NETDEV_BOND_AD_SELECT_COUNT,
-        _NETDEV_BOND_AD_SELECT_MAX,
-        _NETDEV_BOND_AD_SELECT_INVALID = -1,
-} BondAdSelect;
-
-typedef enum BondFailOverMac {
-        NETDEV_BOND_FAIL_OVER_MAC_NONE,
-        NETDEV_BOND_FAIL_OVER_MAC_ACTIVE,
-        NETDEV_BOND_FAIL_OVER_MAC_FOLLOW,
-        _NETDEV_BOND_FAIL_OVER_MAC_MAX,
-        _NETDEV_BOND_FAIL_OVER_MAC_INVALID = -1,
-} BondFailOverMac;
-
-typedef enum BondArpValidate {
-        NETDEV_BOND_ARP_VALIDATE_NONE,
-        NETDEV_BOND_ARP_VALIDATE_ACTIVE,
-        NETDEV_BOND_ARP_VALIDATE_BACKUP,
-        NETDEV_BOND_ARP_VALIDATE_ALL,
-        _NETDEV_BOND_ARP_VALIDATE_MAX,
-        _NETDEV_BOND_ARP_VALIDATE_INVALID = -1,
-} BondArpValidate;
-
-typedef enum BondArpAllTargets {
-        NETDEV_BOND_ARP_ALL_TARGETS_ANY,
-        NETDEV_BOND_ARP_ALL_TARGETS_ALL,
-        _NETDEV_BOND_ARP_ALL_TARGETS_MAX,
-        _NETDEV_BOND_ARP_ALL_TARGETS_INVALID = -1,
-} BondArpAllTargets;
-
-typedef enum BondPrimaryReselect {
-        NETDEV_BOND_PRIMARY_RESELECT_ALWAYS,
-        NETDEV_BOND_PRIMARY_RESELECT_BETTER,
-        NETDEV_BOND_PRIMARY_RESELECT_FAILURE,
-        _NETDEV_BOND_PRIMARY_RESELECT_MAX,
-        _NETDEV_BOND_PRIMARY_RESELECT_INVALID = -1,
-} BondPrimaryReselect;
-
 typedef struct Bond {
         NetDev meta;
 
@@ -122,30 +48,6 @@ extern const NetDevVTable bond_vtable;
 
 int link_set_bond(Link *link);
 
-const char *bond_mode_to_string(BondMode d) _const_;
-BondMode bond_mode_from_string(const char *d) _pure_;
-
-const char *bond_xmit_hash_policy_to_string(BondXmitHashPolicy d) _const_;
-BondXmitHashPolicy bond_xmit_hash_policy_from_string(const char *d) _pure_;
-
-const char *bond_lacp_rate_to_string(BondLacpRate d) _const_;
-BondLacpRate bond_lacp_rate_from_string(const char *d) _pure_;
-
-const char *bond_fail_over_mac_to_string(BondFailOverMac d) _const_;
-BondFailOverMac bond_fail_over_mac_from_string(const char *d) _pure_;
-
-const char *bond_ad_select_to_string(BondAdSelect d) _const_;
-BondAdSelect bond_ad_select_from_string(const char *d) _pure_;
-
-const char *bond_arp_validate_to_string(BondArpValidate d) _const_;
-BondArpValidate bond_arp_validate_from_string(const char *d) _pure_;
-
-const char *bond_arp_all_targets_to_string(BondArpAllTargets d) _const_;
-BondArpAllTargets bond_arp_all_targets_from_string(const char *d) _pure_;
-
-const char *bond_primary_reselect_to_string(BondPrimaryReselect d) _const_;
-BondPrimaryReselect bond_primary_reselect_from_string(const char *d) _pure_;
-
 CONFIG_PARSER_PROTOTYPE(config_parse_bond_mode);
 CONFIG_PARSER_PROTOTYPE(config_parse_bond_xmit_hash_policy);
 CONFIG_PARSER_PROTOTYPE(config_parse_bond_lacp_rate);
index d4555d6fce407f60a4e7d8e1a1062df1b5f9c97f..2761ba774c4c4035e32c64ca4b91b49d62769f3c 100644 (file)
@@ -18,6 +18,7 @@
 #include "sd-network.h"
 
 #include "alloc-util.h"
+#include "bond-util.h"
 #include "bus-common-errors.h"
 #include "bus-error.h"
 #include "bus-util.h"
@@ -116,6 +117,14 @@ typedef struct VxLanInfo {
 
         uint16_t dest_port;
 
+        uint8_t proxy;
+        uint8_t learning;
+        uint8_t inerit;
+        uint8_t rsc;
+        uint8_t l2miss;
+        uint8_t l3miss;
+        uint8_t tos;
+        uint8_t ttl;
 } VxLanInfo;
 
 typedef struct LinkInfo {
@@ -287,6 +296,13 @@ static int decode_netdev(sd_netlink_message *m, LinkInfo *info) {
 
                 (void) sd_netlink_message_read_u32(m, IFLA_VXLAN_LINK, &info->vxlan_info.link);
                 (void) sd_netlink_message_read_u16(m, IFLA_VXLAN_PORT, &info->vxlan_info.dest_port);
+                (void) sd_netlink_message_read_u8(m, IFLA_VXLAN_PROXY, &info->vxlan_info.proxy);
+                (void) sd_netlink_message_read_u8(m, IFLA_VXLAN_LEARNING, &info->vxlan_info.learning);
+                (void) sd_netlink_message_read_u8(m, IFLA_VXLAN_RSC, &info->vxlan_info.rsc);
+                (void) sd_netlink_message_read_u8(m, IFLA_VXLAN_L3MISS, &info->vxlan_info.l3miss);
+                (void) sd_netlink_message_read_u8(m, IFLA_VXLAN_L2MISS, &info->vxlan_info.l2miss);
+                (void) sd_netlink_message_read_u8(m, IFLA_VXLAN_TOS, &info->vxlan_info.tos);
+                (void) sd_netlink_message_read_u8(m, IFLA_VXLAN_TTL, &info->vxlan_info.ttl);
         } else if (streq(received_kind, "vlan"))
                 (void) sd_netlink_message_read_u16(m, IFLA_VLAN_ID, &info->vlan_id);
         else if (STR_IN_SET(received_kind, "ipip", "sit")) {
@@ -1525,22 +1541,10 @@ static int link_status_one(
                                            TABLE_STRING, bridge_state_to_string(info->port_state));
                 }
         } else if (streq_ptr(info->netdev_kind, "bond")) {
-                static const struct {
-                        const char *mode;
-                } mode_table[] = {
-                        { "balance-rr" },
-                        { "active-backup" },
-                        { "balance-xor" },
-                        { "broadcast" },
-                        { "802.3ad" },
-                        { "balance-tlb" },
-                        { "balance-alb" },
-                };
-
                 r = table_add_many(table,
                                    TABLE_EMPTY,
                                    TABLE_STRING, "Mode:",
-                                   TABLE_STRING, mode_table[info->mode],
+                                   TABLE_STRING,  bond_mode_to_string(info->mode),
                                    TABLE_EMPTY,
                                    TABLE_STRING, "Miimon:",
                                    TABLE_TIMESPAN_MSEC, jiffies_to_usec(info->miimon),
@@ -1554,6 +1558,8 @@ static int link_status_one(
                         return table_log_add_error(r);
 
         } else if (streq_ptr(info->netdev_kind, "vxlan")) {
+                char ttl[CONST_MAX(STRLEN("auto") + 1, DECIMAL_STR_MAX(uint8_t))];
+
                 if (info->vxlan_info.vni > 0) {
                         r = table_add_many(table,
                                            TABLE_EMPTY,
@@ -1608,6 +1614,55 @@ static int link_status_one(
                         if (r < 0)
                                  return table_log_add_error(r);
                 }
+
+                r = table_add_many(table,
+                                   TABLE_EMPTY,
+                                   TABLE_STRING, "Learning:",
+                                   TABLE_BOOLEAN, info->vxlan_info.learning);
+                if (r < 0)
+                        return table_log_add_error(r);
+
+                r = table_add_many(table,
+                                   TABLE_EMPTY,
+                                   TABLE_STRING, "RSC:",
+                                   TABLE_BOOLEAN, info->vxlan_info.rsc);
+                if (r < 0)
+                        return table_log_add_error(r);
+
+                r = table_add_many(table,
+                                   TABLE_EMPTY,
+                                   TABLE_STRING, "L3MISS:",
+                                   TABLE_BOOLEAN, info->vxlan_info.l3miss);
+                if (r < 0)
+                        return table_log_add_error(r);
+
+                r = table_add_many(table,
+                                   TABLE_EMPTY,
+                                   TABLE_STRING, "L2MISS:",
+                                   TABLE_BOOLEAN, info->vxlan_info.l2miss);
+                if (r < 0)
+                        return table_log_add_error(r);
+
+                if (info->vxlan_info.tos > 1) {
+                        r = table_add_many(table,
+                                           TABLE_EMPTY,
+                                           TABLE_STRING, "TOS:",
+                                           TABLE_UINT8, info->vxlan_info.tos);
+                        if (r < 0)
+                                return table_log_add_error(r);
+                }
+
+                if (info->vxlan_info.ttl > 0)
+                        xsprintf(ttl, "%" PRIu8, info->vxlan_info.ttl);
+                else
+                        strcpy(ttl, "auto");
+
+                r = table_add_many(table,
+                                   TABLE_EMPTY,
+                                   TABLE_STRING, "TTL:",
+                                   TABLE_STRING, ttl);
+                if (r < 0)
+                        return table_log_add_error(r);
         } else if (streq_ptr(info->netdev_kind, "vlan") && info->vlan_id > 0) {
                 r = table_add_many(table,
                                    TABLE_EMPTY,
index e94de0cfe0b856ad63e4ae1bb6c90ad7d6a45686..ae1c4493c774cf5a1ba1ee937644992b0639e843 100644 (file)
@@ -519,6 +519,82 @@ int config_parse_dhcp_send_option(
         return 0;
 }
 
+int config_parse_dhcp_request_options(
+                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 = data;
+        const char *p;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (isempty(rvalue)) {
+                if (ltype == AF_INET)
+                        network->dhcp_request_options = set_free(network->dhcp_request_options);
+                else
+                        network->dhcp6_request_options = set_free(network->dhcp6_request_options);
+
+                return 0;
+        }
+
+        for (p = rvalue;;) {
+                _cleanup_free_ char *n = NULL;
+                uint32_t i;
+
+                r = extract_first_word(&p, &n, NULL, 0);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to parse DHCP request option, ignoring assignment: %s",
+                                   rvalue);
+                        return 0;
+                }
+                if (r == 0)
+                        return 0;
+
+                r = safe_atou32(n, &i);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "DHCP request option is invalid, ignoring assignment: %s", n);
+                        continue;
+                }
+
+                if (i < 1 || i >= 255) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "DHCP request option is invalid, valid range is 1-254, ignoring assignment: %s", n);
+                        continue;
+                }
+
+                if (ltype == AF_INET)
+                        r = set_ensure_allocated(&network->dhcp_request_options, NULL);
+                else
+                        r = set_ensure_allocated(&network->dhcp6_request_options, NULL);
+                if (r < 0)
+                        return log_oom();
+
+                if (ltype == AF_INET)
+                        r = set_put(network->dhcp_request_options, UINT32_TO_PTR(i));
+                else
+                        r = set_put(network->dhcp6_request_options, UINT32_TO_PTR(i));
+                if (r < 0)
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to store DHCP request option '%s', ignoring assignment: %m", n);
+        }
+
+        return 0;
+}
+
 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains,
                          "Failed to parse DHCP use domains setting");
 
index 0511413a5154b5b194d7941256939b09bc01d5ca..efadcebe21e83c4a8871fe089756f2de80352413 100644 (file)
@@ -51,3 +51,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_mud_url);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_send_option);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_request_options);
index ada14ecd18c8f46ac63e6425fb60261872011937..7d52a3a6a1c635e2a83509b5970c591754475af2 100644 (file)
@@ -1659,72 +1659,6 @@ int config_parse_dhcp_user_class(
         return 0;
 }
 
-int config_parse_dhcp_request_options(
-                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 = data;
-        const char *p;
-        int r;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        if (isempty(rvalue)) {
-                network->dhcp_request_options = set_free(network->dhcp_request_options);
-                return 0;
-        }
-
-        for (p = rvalue;;) {
-                _cleanup_free_ char *n = NULL;
-                uint32_t i;
-
-                r = extract_first_word(&p, &n, NULL, 0);
-                if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r,
-                                   "Failed to parse DHCP request option, ignoring assignment: %s",
-                                   rvalue);
-                        return 0;
-                }
-                if (r == 0)
-                        return 0;
-
-                r = safe_atou32(n, &i);
-                if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r,
-                                   "DHCP request option is invalid, ignoring assignment: %s", n);
-                        continue;
-                }
-
-                if (i < 1 || i >= 255) {
-                        log_syntax(unit, LOG_ERR, filename, line, r,
-                                   "DHCP request option is invalid, valid range is 1-254, ignoring assignment: %s", n);
-                        continue;
-                }
-
-                r = set_ensure_allocated(&network->dhcp_request_options, NULL);
-                if (r < 0)
-                        return log_oom();
-
-                r = set_put(network->dhcp_request_options, UINT32_TO_PTR(i));
-                if (r < 0)
-                        log_syntax(unit, LOG_ERR, filename, line, r,
-                                   "Failed to store DHCP request option '%s', ignoring assignment: %m", n);
-        }
-
-        return 0;
-}
-
 int config_parse_dhcp_ip_service_type(
                 const char *unit,
                 const char *filename,
index b0c30b598ce9ce8cc1962856c289462dbcf3b1e1..78e10d9299050d1f9b7560ca082dc87e40b6370d 100644 (file)
@@ -26,6 +26,5 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_black_listed_ip_address);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_request_options);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_ip_service_type);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_mud_url);
index 78c99e95bb4b8e0e33e539ce0155fc91ec6f6949..05df41cd3a7bb448633fd38fce51dbebe9e71fcc 100644 (file)
@@ -621,6 +621,7 @@ static int dhcp6_set_hostname(sd_dhcp6_client *client, Link *link) {
 int dhcp6_configure(Link *link) {
         _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
         sd_dhcp6_option *send_option;
+        void *request_options;
         const DUID *duid;
         Iterator i;
         int r;
@@ -692,6 +693,19 @@ int dhcp6_configure(Link *link) {
                         return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set MUD URL: %m");
         }
 
+        SET_FOREACH(request_options, link->network->dhcp6_request_options, i) {
+                uint32_t option = PTR_TO_UINT32(request_options);
+
+                r = sd_dhcp6_client_set_request_option(client, option);
+                if (r == -EEXIST) {
+                        log_link_debug(link, "DHCP6 CLIENT: Failed to set request flag for '%u' already exists, ignoring.", option);
+                        continue;
+                }
+
+                if (r < 0)
+                        return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set request flag for '%u': %m", option);
+        }
+
         r = sd_dhcp6_client_set_callback(client, dhcp6_handler, link);
         if (r < 0)
                 return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set callback: %m");
index d709633df34012f34005741f8965d1b4015dfd0f..711bec7588e2317ad89e0efba54c1e4c4e4e54d6 100644 (file)
@@ -166,7 +166,7 @@ DHCPv4.UseHostname,                          config_parse_bool,
 DHCPv4.UseDomains,                           config_parse_dhcp_use_domains,                            0,                             offsetof(Network, dhcp_use_domains)
 DHCPv4.UseRoutes,                            config_parse_bool,                                        0,                             offsetof(Network, dhcp_use_routes)
 DHCPv4.UseGateway,                           config_parse_tristate,                                    0,                             offsetof(Network, dhcp_use_gateway)
-DHCPv4.RequestOptions,                       config_parse_dhcp_request_options,                        0,                             0
+DHCPv4.RequestOptions,                       config_parse_dhcp_request_options,                        AF_INET,                       0
 DHCPv4.Anonymize,                            config_parse_bool,                                        0,                             offsetof(Network, dhcp_anonymize)
 DHCPv4.SendHostname,                         config_parse_bool,                                        0,                             offsetof(Network, dhcp_send_hostname)
 DHCPv4.Hostname,                             config_parse_hostname,                                    0,                             offsetof(Network, dhcp_hostname)
@@ -193,6 +193,7 @@ DHCPv6.UseDNS,                               config_parse_bool,
 DHCPv6.UseNTP,                               config_parse_bool,                                        0,                             offsetof(Network, dhcp6_use_ntp)
 DHCPv6.RapidCommit,                          config_parse_bool,                                        0,                             offsetof(Network, rapid_commit)
 DHCPv6.MUDURL,                               config_parse_dhcp6_mud_url,                               0,                             0
+DHCPv6.RequestOptions,                       config_parse_dhcp_request_options,                        AF_INET6,                      0
 DHCPv6.ForceDHCPv6PDOtherInformation,        config_parse_bool,                                        0,                             offsetof(Network, dhcp6_force_pd_other_information)
 DHCPv6.PrefixDelegationHint,                 config_parse_dhcp6_pd_hint,                               0,                             0
 DHCPv6.WithoutRA,                            config_parse_bool,                                        0,                             offsetof(Network, dhcp6_without_ra)
index 4ba46d28e308752c826e35d39a275ad22eb76a3f..a15f884ab080a74716c221013d533938f77a6c9b 100644 (file)
@@ -650,6 +650,7 @@ static Network *network_free(Network *network) {
         free(network->dhcp_hostname);
         set_free(network->dhcp_black_listed_ip);
         set_free(network->dhcp_request_options);
+        set_free(network->dhcp6_request_options);
         free(network->mac);
         free(network->dhcp6_mudurl);
 
index 092e58d42c9c98f804ea63e3ee24615e84e92168..019bd7676b18256cd11a49b305d6554ab3a6ec75 100644 (file)
@@ -134,6 +134,7 @@ struct Network {
         char *dhcp6_mudurl;
         struct in6_addr dhcp6_pd_address;
         OrderedHashmap *dhcp6_client_send_options;
+        Set *dhcp6_request_options;
 
         /* DHCP Server Support */
         bool dhcp_server;
index cbad1dce6058df10cf3e7fb9d22416d784d67617..cbaef5e49c65f986b6530774c419df1ef094249f 100644 (file)
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
+#include <sys/stat.h>
+
 #include "sd-event.h"
 #include "sd-netlink.h"
 #include "sd-network.h"
@@ -71,7 +73,7 @@ struct Manager {
         bool need_builtin_fallbacks:1;
 
         bool read_resolv_conf:1;
-        usec_t resolv_conf_mtime;
+        struct stat resolv_conf_stat;
 
         DnsTrustAnchor trust_anchor;
 
index c06213f4867fd2bed64e5a60436c926daea03ce7..97aee7abc816ba756e83bad37212c9bac92f02a4 100644 (file)
@@ -14,6 +14,7 @@
 #include "resolved-conf.h"
 #include "resolved-dns-server.h"
 #include "resolved-resolv-conf.h"
+#include "stat-util.h"
 #include "string-util.h"
 #include "strv.h"
 #include "tmpfile-util-label.h"
@@ -93,7 +94,7 @@ int manager_read_resolv_conf(Manager *m) {
         }
 
         /* Have we already seen the file? */
-        if (timespec_load(&st.st_mtim) == m->resolv_conf_mtime)
+        if (stat_inode_unmodified(&st, &m->resolv_conf_stat))
                 return 0;
 
         if (file_is_our_own(&st))
@@ -159,7 +160,7 @@ int manager_read_resolv_conf(Manager *m) {
                 log_syntax(NULL, LOG_DEBUG, "/etc/resolv.conf", n, 0, "Ignoring resolv.conf line: %s", l);
         }
 
-        m->resolv_conf_mtime = timespec_load(&st.st_mtim);
+        m->resolv_conf_stat = st;
 
         /* Flush out all servers and search domains that are still
          * marked. Those are then ones that didn't appear in the new
diff --git a/src/shared/bond-util.c b/src/shared/bond-util.c
new file mode 100644 (file)
index 0000000..2296ecd
--- /dev/null
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bond-util.h"
+#include "string-table.h"
+
+static const char* const bond_mode_table[_NETDEV_BOND_MODE_MAX] = {
+        [NETDEV_BOND_MODE_BALANCE_RR] = "balance-rr",
+        [NETDEV_BOND_MODE_ACTIVE_BACKUP] = "active-backup",
+        [NETDEV_BOND_MODE_BALANCE_XOR] = "balance-xor",
+        [NETDEV_BOND_MODE_BROADCAST] = "broadcast",
+        [NETDEV_BOND_MODE_802_3AD] = "802.3ad",
+        [NETDEV_BOND_MODE_BALANCE_TLB] = "balance-tlb",
+        [NETDEV_BOND_MODE_BALANCE_ALB] = "balance-alb",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(bond_mode, BondMode);
+
+static const char* const bond_xmit_hash_policy_table[_NETDEV_BOND_XMIT_HASH_POLICY_MAX] = {
+        [NETDEV_BOND_XMIT_HASH_POLICY_LAYER2] = "layer2",
+        [NETDEV_BOND_XMIT_HASH_POLICY_LAYER34] = "layer3+4",
+        [NETDEV_BOND_XMIT_HASH_POLICY_LAYER23] = "layer2+3",
+        [NETDEV_BOND_XMIT_HASH_POLICY_ENCAP23] = "encap2+3",
+        [NETDEV_BOND_XMIT_HASH_POLICY_ENCAP34] = "encap3+4",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(bond_xmit_hash_policy, BondXmitHashPolicy);
+
+static const char* const bond_lacp_rate_table[_NETDEV_BOND_LACP_RATE_MAX] = {
+        [NETDEV_BOND_LACP_RATE_SLOW] = "slow",
+        [NETDEV_BOND_LACP_RATE_FAST] = "fast",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(bond_lacp_rate, BondLacpRate);
+
+static const char* const bond_ad_select_table[_NETDEV_BOND_AD_SELECT_MAX] = {
+        [NETDEV_BOND_AD_SELECT_STABLE] = "stable",
+        [NETDEV_BOND_AD_SELECT_BANDWIDTH] = "bandwidth",
+        [NETDEV_BOND_AD_SELECT_COUNT] = "count",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(bond_ad_select, BondAdSelect);
+
+static const char* const bond_fail_over_mac_table[_NETDEV_BOND_FAIL_OVER_MAC_MAX] = {
+        [NETDEV_BOND_FAIL_OVER_MAC_NONE] = "none",
+        [NETDEV_BOND_FAIL_OVER_MAC_ACTIVE] = "active",
+        [NETDEV_BOND_FAIL_OVER_MAC_FOLLOW] = "follow",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(bond_fail_over_mac, BondFailOverMac);
+
+static const char *const bond_arp_validate_table[_NETDEV_BOND_ARP_VALIDATE_MAX] = {
+        [NETDEV_BOND_ARP_VALIDATE_NONE] = "none",
+        [NETDEV_BOND_ARP_VALIDATE_ACTIVE]= "active",
+        [NETDEV_BOND_ARP_VALIDATE_BACKUP]= "backup",
+        [NETDEV_BOND_ARP_VALIDATE_ALL]= "all",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(bond_arp_validate, BondArpValidate);
+
+static const char *const bond_arp_all_targets_table[_NETDEV_BOND_ARP_ALL_TARGETS_MAX] = {
+        [NETDEV_BOND_ARP_ALL_TARGETS_ANY] = "any",
+        [NETDEV_BOND_ARP_ALL_TARGETS_ALL] = "all",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(bond_arp_all_targets, BondArpAllTargets);
+
+static const char *const bond_primary_reselect_table[_NETDEV_BOND_PRIMARY_RESELECT_MAX] = {
+        [NETDEV_BOND_PRIMARY_RESELECT_ALWAYS] = "always",
+        [NETDEV_BOND_PRIMARY_RESELECT_BETTER]= "better",
+        [NETDEV_BOND_PRIMARY_RESELECT_FAILURE]= "failure",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(bond_primary_reselect, BondPrimaryReselect);
diff --git a/src/shared/bond-util.h b/src/shared/bond-util.h
new file mode 100644 (file)
index 0000000..66f86e7
--- /dev/null
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <netinet/in.h>
+#include <linux/if_bonding.h>
+
+#include "macro.h"
+
+/*
+ * Maximum number of targets supported by the kernel for a single
+ * bond netdev.
+ */
+#define NETDEV_BOND_ARP_TARGETS_MAX 16
+
+typedef enum BondMode {
+        NETDEV_BOND_MODE_BALANCE_RR    = BOND_MODE_ROUNDROBIN,
+        NETDEV_BOND_MODE_ACTIVE_BACKUP = BOND_MODE_ACTIVEBACKUP,
+        NETDEV_BOND_MODE_BALANCE_XOR   = BOND_MODE_XOR,
+        NETDEV_BOND_MODE_BROADCAST     = BOND_MODE_BROADCAST,
+        NETDEV_BOND_MODE_802_3AD       = BOND_MODE_8023AD,
+        NETDEV_BOND_MODE_BALANCE_TLB   = BOND_MODE_TLB,
+        NETDEV_BOND_MODE_BALANCE_ALB   = BOND_MODE_ALB,
+        _NETDEV_BOND_MODE_MAX,
+        _NETDEV_BOND_MODE_INVALID      = -1
+} BondMode;
+
+typedef enum BondXmitHashPolicy {
+        NETDEV_BOND_XMIT_HASH_POLICY_LAYER2   = BOND_XMIT_POLICY_LAYER2,
+        NETDEV_BOND_XMIT_HASH_POLICY_LAYER34  = BOND_XMIT_POLICY_LAYER34,
+        NETDEV_BOND_XMIT_HASH_POLICY_LAYER23  = BOND_XMIT_POLICY_LAYER23,
+        NETDEV_BOND_XMIT_HASH_POLICY_ENCAP23  = BOND_XMIT_POLICY_ENCAP23,
+        NETDEV_BOND_XMIT_HASH_POLICY_ENCAP34  = BOND_XMIT_POLICY_ENCAP34,
+        _NETDEV_BOND_XMIT_HASH_POLICY_MAX,
+        _NETDEV_BOND_XMIT_HASH_POLICY_INVALID = -1
+} BondXmitHashPolicy;
+
+typedef enum BondLacpRate {
+        NETDEV_BOND_LACP_RATE_SLOW,
+        NETDEV_BOND_LACP_RATE_FAST,
+        _NETDEV_BOND_LACP_RATE_MAX,
+        _NETDEV_BOND_LACP_RATE_INVALID = -1,
+} BondLacpRate;
+
+typedef enum BondAdSelect {
+        NETDEV_BOND_AD_SELECT_STABLE,
+        NETDEV_BOND_AD_SELECT_BANDWIDTH,
+        NETDEV_BOND_AD_SELECT_COUNT,
+        _NETDEV_BOND_AD_SELECT_MAX,
+        _NETDEV_BOND_AD_SELECT_INVALID = -1,
+} BondAdSelect;
+
+typedef enum BondFailOverMac {
+        NETDEV_BOND_FAIL_OVER_MAC_NONE,
+        NETDEV_BOND_FAIL_OVER_MAC_ACTIVE,
+        NETDEV_BOND_FAIL_OVER_MAC_FOLLOW,
+        _NETDEV_BOND_FAIL_OVER_MAC_MAX,
+        _NETDEV_BOND_FAIL_OVER_MAC_INVALID = -1,
+} BondFailOverMac;
+
+typedef enum BondArpValidate {
+        NETDEV_BOND_ARP_VALIDATE_NONE,
+        NETDEV_BOND_ARP_VALIDATE_ACTIVE,
+        NETDEV_BOND_ARP_VALIDATE_BACKUP,
+        NETDEV_BOND_ARP_VALIDATE_ALL,
+        _NETDEV_BOND_ARP_VALIDATE_MAX,
+        _NETDEV_BOND_ARP_VALIDATE_INVALID = -1,
+} BondArpValidate;
+
+typedef enum BondArpAllTargets {
+        NETDEV_BOND_ARP_ALL_TARGETS_ANY,
+        NETDEV_BOND_ARP_ALL_TARGETS_ALL,
+        _NETDEV_BOND_ARP_ALL_TARGETS_MAX,
+        _NETDEV_BOND_ARP_ALL_TARGETS_INVALID = -1,
+} BondArpAllTargets;
+
+typedef enum BondPrimaryReselect {
+        NETDEV_BOND_PRIMARY_RESELECT_ALWAYS,
+        NETDEV_BOND_PRIMARY_RESELECT_BETTER,
+        NETDEV_BOND_PRIMARY_RESELECT_FAILURE,
+        _NETDEV_BOND_PRIMARY_RESELECT_MAX,
+        _NETDEV_BOND_PRIMARY_RESELECT_INVALID = -1,
+} BondPrimaryReselect;
+
+const char *bond_mode_to_string(BondMode d) _const_;
+BondMode bond_mode_from_string(const char *d) _pure_;
+
+const char *bond_xmit_hash_policy_to_string(BondXmitHashPolicy d) _const_;
+BondXmitHashPolicy bond_xmit_hash_policy_from_string(const char *d) _pure_;
+
+const char *bond_lacp_rate_to_string(BondLacpRate d) _const_;
+BondLacpRate bond_lacp_rate_from_string(const char *d) _pure_;
+
+const char *bond_fail_over_mac_to_string(BondFailOverMac d) _const_;
+BondFailOverMac bond_fail_over_mac_from_string(const char *d) _pure_;
+
+const char *bond_ad_select_to_string(BondAdSelect d) _const_;
+BondAdSelect bond_ad_select_from_string(const char *d) _pure_;
+
+const char *bond_arp_validate_to_string(BondArpValidate d) _const_;
+BondArpValidate bond_arp_validate_from_string(const char *d) _pure_;
+
+const char *bond_arp_all_targets_to_string(BondArpAllTargets d) _const_;
+BondArpAllTargets bond_arp_all_targets_from_string(const char *d) _pure_;
+
+const char *bond_primary_reselect_to_string(BondPrimaryReselect d) _const_;
+BondPrimaryReselect bond_primary_reselect_from_string(const char *d) _pure_;
index c83a4ba0eb8a86a297e3a78e18d58a1ea53b595d..bf3b5fa1622800a26edfedaf75720bb03d61600c 100644 (file)
@@ -546,30 +546,47 @@ static int condition_test_capability(Condition *c, char **env) {
 }
 
 static int condition_test_needs_update(Condition *c, char **env) {
-        const char *p;
         struct stat usr, other;
+        const char *p;
+        bool b;
+        int r;
 
         assert(c);
         assert(c->parameter);
         assert(c->type == CONDITION_NEEDS_UPDATE);
 
+        r = proc_cmdline_get_bool("systemd.condition-needs-update", &b);
+        if (r < 0)
+                log_debug_errno(r, "Failed to parse systemd.condition-needs-update= kernel command line argument, ignoring: %m");
+        if (r > 0)
+                return b;
+
+        if (!path_is_absolute(c->parameter)) {
+                log_debug("Specified condition parameter '%s' is not absolute, assuming an update is needed.", c->parameter);
+                return true;
+        }
+
         /* If the file system is read-only we shouldn't suggest an update */
-        if (path_is_read_only_fs(c->parameter) > 0)
+        r = path_is_read_only_fs(c->parameter);
+        if (r < 0)
+                log_debug_errno(r, "Failed to determine if '%s' is read-only, ignoring: %m", c->parameter);
+        if (r > 0)
                 return false;
 
-        /* Any other failure means we should allow the condition to be true,
-         * so that we rather invoke too many update tools than too
-         * few. */
-
-        if (!path_is_absolute(c->parameter))
-                return true;
+        /* Any other failure means we should allow the condition to be true, so that we rather invoke too
+         * many update tools than too few. */
 
         p = strjoina(c->parameter, "/.updated");
-        if (lstat(p, &other) < 0)
+        if (lstat(p, &other) < 0) {
+                if (errno != ENOENT)
+                        log_debug_errno(errno, "Failed to stat() '%s', assuming an update is needed: %m", p);
                 return true;
+        }
 
-        if (lstat("/usr/", &usr) < 0)
+        if (lstat("/usr/", &usr) < 0) {
+                log_debug_errno(errno, "Failed to stat() /usr/, assuming an update is needed: %m");
                 return true;
+        }
 
         /*
          * First, compare seconds as they are always accurate...
@@ -585,44 +602,52 @@ static int condition_test_needs_update(Condition *c, char **env) {
          * AND the target file's nanoseconds == 0
          * (otherwise the filesystem supports nsec timestamps, see stat(2)).
          */
-        if (usr.st_mtim.tv_nsec > 0 && other.st_mtim.tv_nsec == 0) {
-                _cleanup_free_ char *timestamp_str = NULL;
-                uint64_t timestamp;
-                int r;
-
-                r = parse_env_file(NULL, p, "TIMESTAMP_NSEC", &timestamp_str);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to parse timestamp file '%s', using mtime: %m", p);
-                        return true;
-                } else if (r == 0) {
-                        log_debug("No data in timestamp file '%s', using mtime", p);
-                        return true;
-                }
+        if (usr.st_mtim.tv_nsec == 0 || other.st_mtim.tv_nsec > 0)
+                return usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec;
 
-                r = safe_atou64(timestamp_str, &timestamp);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to parse timestamp value '%s' in file '%s', using mtime: %m", timestamp_str, p);
-                        return true;
-                }
+        _cleanup_free_ char *timestamp_str = NULL;
+        r = parse_env_file(NULL, p, "TIMESTAMP_NSEC", &timestamp_str);
+        if (r < 0) {
+                log_debug_errno(r, "Failed to parse timestamp file '%s', using mtime: %m", p);
+                return true;
+        } else if (r == 0) {
+                log_debug("No data in timestamp file '%s', using mtime.", p);
+                return true;
+        }
 
-                timespec_store(&other.st_mtim, timestamp);
+        uint64_t timestamp;
+        r = safe_atou64(timestamp_str, &timestamp);
+        if (r < 0) {
+                log_debug_errno(r, "Failed to parse timestamp value '%s' in file '%s', using mtime: %m", timestamp_str, p);
+                return true;
         }
 
-        return usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec;
+        return timespec_load_nsec(&usr.st_mtim) > timestamp;
 }
 
 static int condition_test_first_boot(Condition *c, char **env) {
-        int r;
+        int r, q;
+        bool b;
 
         assert(c);
         assert(c->parameter);
         assert(c->type == CONDITION_FIRST_BOOT);
 
+        r = proc_cmdline_get_bool("systemd.condition-first-boot", &b);
+        if (r < 0)
+                log_debug_errno(r, "Failed to parse systemd.condition-first-boot= kernel command line argument, ignoring: %m");
+        if (r > 0)
+                return b == !!r;
+
         r = parse_boolean(c->parameter);
         if (r < 0)
                 return r;
 
-        return (access("/run/systemd/first-boot", F_OK) >= 0) == !!r;
+        q = access("/run/systemd/first-boot", F_OK);
+        if (q < 0 && errno != ENOENT)
+                log_debug_errno(errno, "Failed to check if /run/systemd/first-boot exists, ignoring: %m");
+
+        return (q >= 0) == !!r;
 }
 
 static int condition_test_environment(Condition *c, char **env) {
index d3adecc9e7cead2f03f531541031fa905036517c..e3aee57ac816e7ae9e96c1ec1d4fcb32e52606d6 100644 (file)
@@ -17,6 +17,8 @@ shared_sources = files('''
         bitmap.c
         bitmap.h
         blkid-util.h
+        bond-util.c
+        bond-util.h
         boot-timestamps.c
         boot-timestamps.h
         bootspec.c
index f2423ba456a3bbc4128645f4173811bfc3ec9679..b10a3e04bc3490cb7d50987126433f1fb095138c 100644 (file)
@@ -44,6 +44,7 @@ enum {
         SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION  = 1ULL << 6,
         SD_BUS_VTABLE_PROPERTY_EXPLICIT            = 1ULL << 7,
         SD_BUS_VTABLE_SENSITIVE                    = 1ULL << 8, /* covers both directions: method call + reply */
+        SD_BUS_VTABLE_ABSOLUTE_OFFSET              = 1ULL << 9,
         _SD_BUS_VTABLE_CAPABILITY_MASK             = 0xFFFFULL << 40
 };
 
index 82399f7b1a7808b8d13ef3dcb1eef92cf253c6ce..743ab903ea8cff9c5d14956e6d630bce69d6d9a8 100644 (file)
@@ -114,6 +114,7 @@ PrefixDelegationHint=
 WithoutRA=
 MUDURL=
 SendOption=
+RequestOptions=
 [Route]
 Destination=
 Protocol=