]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #632 from Stebalien/cgls-nspawn
authorDaniel Mack <github@zonque.org>
Wed, 22 Jul 2015 22:43:00 +0000 (00:43 +0200)
committerDaniel Mack <github@zonque.org>
Wed, 22 Jul 2015 22:43:00 +0000 (00:43 +0200)
Machines can also be services

32 files changed:
TODO
configure.ac
hwdb/70-mouse.hwdb
man/systemd.netdev.xml
man/systemd.network.xml
src/basic/macro.h
src/basic/missing.h
src/bootchart/bootchart.c
src/core/automount.c
src/core/busname.c
src/core/job.c
src/core/mount.c
src/core/service.c
src/core/slice.c
src/core/socket.c
src/core/swap.c
src/core/target.c
src/core/unit.c
src/core/unit.h
src/libsystemd/sd-bus/bus-control.c
src/libsystemd/sd-netlink/netlink-types.c
src/login/logind-dbus.c
src/network/networkd-dhcp4.c
src/network/networkd-netdev-gperf.gperf
src/network/networkd-netdev-tunnel.c
src/network/networkd-netdev-tunnel.h
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd.h
src/udev/ata_id/ata_id.c
src/udev/udevd.c
src/user-sessions/user-sessions.c

diff --git a/TODO b/TODO
index 3a2b4cf9f065ef89d3f3b1ecd020bd4d42862385..4ac1f829d58755b7d1ae2336d5d0de0d185b3144 100644 (file)
--- a/TODO
+++ b/TODO
@@ -321,8 +321,6 @@ Features:
   - add LLDP client side support
   - the DHCP lease data (such as NTP/DNS) is still made available when
     a carrier is lost on a link. It should be removed instantly.
-  - .network setting that allows overriding of the hostname to send to the dhcp server
-    http://lists.freedesktop.org/archives/systemd-devel/2014-July/021550.html
   - expose in the API the following bits:
         - option 15, domain name and/or option 119, search list
         - option 12, host name and/or option 81, fqdn
index 999f9f84d3b2d4f9c262ff882187424863210351..ff6364aba25c793f2198cbabf0202d3961032bfa 100644 (file)
@@ -299,7 +299,8 @@ AC_CHECK_DECLS([IFLA_INET6_ADDR_GEN_MODE,
                 IFLA_BOND_AD_INFO,
                 IFLA_VLAN_PROTOCOL,
                 IFLA_VXLAN_REMCSUM_NOPARTIAL,
-                IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
+                IFLA_IPTUN_ENCAP_DPORT,
+                IFLA_GRE_ENCAP_DPORT,
                 IFLA_BRIDGE_VLAN_INFO,
                 IFLA_BRPORT_UNICAST_FLOOD,
                 NDA_IFINDEX,
index 16333215026ece05b6a83e1dfe9ca73496194fd3..bc4b597bbf1874768463afb5683b7c32f1232769 100644 (file)
@@ -247,6 +247,10 @@ mouse:usb:v046dpc05a:name:Logitech USB Optical Mouse:
 mouse:usb:v046dpc065:name:Logitech USB Laser Mouse:
  MOUSE_DPI=1000@125
 
+# Logitech MX Master
+mouse:usb:v046dp4041:name:Logitech MX Master:
+ MOUSE_DPI=1000@166
+
 # Logitech MK260 Wireless Combo Receiver aka M-R0011
 mouse:usb:v046dpc52e:name:Logitech USB Receiver:
  MOUSE_DPI=1000@200
index ff7b85453f7972e89a76790c65a39fc166b8579a..d15c21be60c082e4737e7b735c664699c5b608a2 100644 (file)
           the tunnel.</para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>IPv6FlowLabel=</varname></term>
+        <listitem>
+          <para>Configures The 20-bit Flow Label (see <ulink url="https://tools.ietf.org/html/rfc6437">
+          RFC 6437</ulink>) field in the IPv6 header (see <ulink url="https://tools.ietf.org/html/rfc2460">
+          RFC 2460</ulink>), is used by a node to label packets of a flow.
+          It's only used for IPv6 Tunnels.
+          A Flow Label of zero is used to indicate packets that have
+          not been labeled. Takes following values.
+          When <literal>inherit</literal> it uses the original flowlabel,
+          or can be configured to any value betwen 0 to 0xFFFFF.</para>
+        </listitem>
+      </varlistentry>
       <varlistentry>
         <term><varname>Mode=</varname></term>
         <listitem>
index ff01da624947a65a6daa051989d4532d3d745100..90a0e8fff669ca68fd421c3bedff2d80792f2437 100644 (file)
             hostname.</para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+        <term><varname>Hostname=</varname></term>
+        <listitem>
+          <para>Hostname is a option to override the machine's hostname that will be sent to the DHCP server</para>
+        </listitem>
+      </varlistentry>
         <varlistentry>
           <term><varname>UseDomains=</varname></term>
           <listitem>
index 5fa17ed2085cdc2fe3a7b992468f5917d6cd96b0..ea01d701d29e789d23e36d887462069de8cfd181 100644 (file)
@@ -406,12 +406,12 @@ do {                                                                    \
 
 #define IN_SET(x, y, ...)                                               \
         ({                                                              \
-                const typeof(y) _y = (y);                               \
-                const typeof(_y) _x = (x);                              \
+                static const typeof(y) _array[] = { (y), __VA_ARGS__ }; \
+                const typeof(y) _x = (x);                               \
                 unsigned _i;                                            \
                 bool _found = false;                                    \
-                for (_i = 0; _i < 1 + sizeof((const typeof(_x)[]) { __VA_ARGS__ })/sizeof(const typeof(_x)); _i++) \
-                        if (((const typeof(_x)[]) { _y, __VA_ARGS__ })[_i] == _x) { \
+                for (_i = 0; _i < ELEMENTSOF(_array); _i++)             \
+                        if (_array[_i] == _x) {                         \
                                 _found = true;                          \
                                 break;                                  \
                         }                                               \
index be7f6186fcfb1fd556ed85c2ddcdb4fc7adcf21e..bd49f10e7618ec4e90c8f30353a216e44ace46ce 100644 (file)
@@ -772,7 +772,7 @@ static inline int setns(int fd, int nstype) {
 #define IFLA_VXLAN_MAX  (__IFLA_VXLAN_MAX - 1)
 #endif
 
-#if !HAVE_DECL_IFLA_IPTUN_6RD_RELAY_PREFIXLEN
+#if !HAVE_DECL_IFLA_IPTUN_ENCAP_DPORT
 #define IFLA_IPTUN_UNSPEC 0
 #define IFLA_IPTUN_LINK 1
 #define IFLA_IPTUN_LOCAL 2
@@ -788,11 +788,41 @@ static inline int setns(int fd, int nstype) {
 #define IFLA_IPTUN_6RD_RELAY_PREFIX 12
 #define IFLA_IPTUN_6RD_PREFIXLEN 13
 #define IFLA_IPTUN_6RD_RELAY_PREFIXLEN 14
-#define __IFLA_IPTUN_MAX 15
+#define IFLA_IPTUN_ENCAP_TYPE 15
+#define IFLA_IPTUN_ENCAP_FLAGS 16
+#define IFLA_IPTUN_ENCAP_SPORT 17
+#define IFLA_IPTUN_ENCAP_DPORT 18
+
+#define __IFLA_IPTUN_MAX 19
 
 #define IFLA_IPTUN_MAX  (__IFLA_IPTUN_MAX - 1)
 #endif
 
+#if !HAVE_DECL_IFLA_GRE_ENCAP_DPORT
+#define IFLA_GRE_UNSPEC 0
+#define IFLA_GRE_LINK 1
+#define IFLA_GRE_IFLAGS 2
+#define IFLA_GRE_OFLAGS 3
+#define IFLA_GRE_IKEY 4
+#define IFLA_GRE_OKEY 5
+#define IFLA_GRE_LOCAL 6
+#define IFLA_GRE_REMOTE 7
+#define IFLA_GRE_TTL 8
+#define IFLA_GRE_TOS 9
+#define IFLA_GRE_PMTUDISC 10
+#define IFLA_GRE_ENCAP_LIMIT 11
+#define IFLA_GRE_FLOWINFO 12
+#define IFLA_GRE_FLAGS 13
+#define IFLA_GRE_ENCAP_TYPE 14
+#define IFLA_GRE_ENCAP_FLAGS 15
+#define IFLA_GRE_ENCAP_SPORT 16
+#define IFLA_GRE_ENCAP_DPORT 17
+
+#define __IFLA_GRE_MAX 18
+
+#define IFLA_GRE_MAX  (__IFLA_GRE_MAX - 1)
+#endif
+
 #if !HAVE_DECL_IFLA_BRIDGE_VLAN_INFO
 #define IFLA_BRIDGE_FLAGS 0
 #define IFLA_BRIDGE_MODE 1
index 3360bc85beae34431cde9cb8c3593694a3efe918..1625d51fa8098c9b982bb09a790d9cf5d1c5c7ce 100644 (file)
@@ -387,9 +387,6 @@ int main(int argc, char *argv[]) {
         for (samples = 0; !exiting && samples < arg_samples_len; samples++) {
                 int res;
                 double sample_stop;
-                struct timespec req;
-                time_t newint_s;
-                long newint_ns;
                 double elapsed;
                 double timeleft;
 
@@ -427,18 +424,17 @@ int main(int argc, char *argv[]) {
                 elapsed = (sample_stop - sampledata->sampletime) * 1000000000.0;
                 timeleft = interval - elapsed;
 
-                newint_s = (time_t)(timeleft / 1000000000.0);
-                newint_ns = (long)(timeleft - (newint_s * 1000000000.0));
-
                 /*
                  * check if we have not consumed our entire timeslice. If we
                  * do, don't sleep and take a new sample right away.
                  * we'll lose all the missed samples and overrun our total
                  * time
                  */
-                if (newint_ns > 0 || newint_s > 0) {
-                        req.tv_sec = newint_s;
-                        req.tv_nsec = newint_ns;
+                if (timeleft > 0) {
+                        struct timespec req;
+
+                        req.tv_sec = (time_t)(timeleft / 1000000000.0);
+                        req.tv_nsec = (long)(timeleft - (req.tv_sec * 1000000000.0));
 
                         res = nanosleep(&req, NULL);
                         if (res) {
@@ -452,7 +448,7 @@ int main(int argc, char *argv[]) {
                 } else {
                         overrun++;
                         /* calculate how many samples we lost and scrap them */
-                        arg_samples_len -= (int)(newint_ns / interval);
+                        arg_samples_len -= (int)(-timeleft / interval);
                 }
                 LIST_PREPEND(link, head, sampledata);
         }
index d847dc1629d7f5f8f001af1addea299ac9512345..90b331f70ea19c2ed45ac8d96ef9d33bb0619dd1 100644 (file)
@@ -1066,7 +1066,6 @@ const UnitVTable automount_vtable = {
                 .finished_start_job = {
                         [JOB_DONE]       = "Set up automount %s.",
                         [JOB_FAILED]     = "Failed to set up automount %s.",
-                        [JOB_DEPENDENCY] = "Dependency failed for %s.",
                 },
                 .finished_stop_job = {
                         [JOB_DONE]       = "Unset automount %s.",
index 2085721546fa15c0770ac6475d59fefa22fb20c6..9530a8731178f8de72248d9b1e2e42a00f89a254 100644 (file)
@@ -1065,13 +1065,10 @@ const UnitVTable busname_vtable = {
                 .finished_start_job = {
                         [JOB_DONE]       = "Listening on %s.",
                         [JOB_FAILED]     = "Failed to listen on %s.",
-                        [JOB_DEPENDENCY] = "Dependency failed for %s.",
-                        [JOB_TIMEOUT]    = "Timed out starting %s.",
                 },
                 .finished_stop_job = {
                         [JOB_DONE]       = "Closed %s.",
                         [JOB_FAILED]     = "Failed stopping %s.",
-                        [JOB_TIMEOUT]    = "Timed out stopping %s.",
                 },
         },
 };
index 1448e5b69afcba68e069d61d9c550156ef85a51c..15f5cc0cc9327af6ad92be221735cdbc162a5f89 100644 (file)
@@ -495,10 +495,48 @@ static void job_change_type(Job *j, JobType newtype) {
         j->type = newtype;
 }
 
+static int job_perform_on_unit(Job **j) {
+        /* While we execute this operation the job might go away (for
+         * example: because it finishes immediately or is replaced by a new,
+         * conflicting job.) To make sure we don't access a freed job later on
+         * we store the id here, so that we can verify the job is still
+         * valid. */
+        Manager *m  = (*j)->manager;
+        Unit *u     = (*j)->unit;
+        JobType t   = (*j)->type;
+        uint32_t id = (*j)->id;
+        int r;
+
+        switch (t) {
+                case JOB_START:
+                        r = unit_start(u);
+                        break;
+
+                case JOB_RESTART:
+                        t = JOB_STOP;
+                case JOB_STOP:
+                        r = unit_stop(u);
+                        break;
+
+                case JOB_RELOAD:
+                        r = unit_reload(u);
+                        break;
+
+                default:
+                        assert_not_reached("Invalid job type");
+        }
+
+        /* Log if the job still exists and the start/stop/reload function
+         * actually did something. */
+        *j = manager_get_job(m, id);
+        if (*j && r > 0)
+                unit_status_emit_starting_stopping_reloading(u, t);
+
+        return r;
+}
+
 int job_run_and_invalidate(Job *j) {
         int r;
-        uint32_t id;
-        Manager *m = j->manager;
 
         assert(j);
         assert(j->installed);
@@ -517,23 +555,9 @@ int job_run_and_invalidate(Job *j) {
         job_set_state(j, JOB_RUNNING);
         job_add_to_dbus_queue(j);
 
-        /* While we execute this operation the job might go away (for
-         * example: because it is replaced by a new, conflicting
-         * job.) To make sure we don't access a freed job later on we
-         * store the id here, so that we can verify the job is still
-         * valid. */
-        id = j->id;
 
         switch (j->type) {
 
-                case JOB_START:
-                        r = unit_start(j->unit);
-
-                        /* If this unit cannot be started, then simply wait */
-                        if (r == -EBADR)
-                                r = 0;
-                        break;
-
                 case JOB_VERIFY_ACTIVE: {
                         UnitActiveState t = unit_active_state(j->unit);
                         if (UNIT_IS_ACTIVE_OR_RELOADING(t))
@@ -545,17 +569,19 @@ int job_run_and_invalidate(Job *j) {
                         break;
                 }
 
+                case JOB_START:
                 case JOB_STOP:
                 case JOB_RESTART:
-                        r = unit_stop(j->unit);
+                        r = job_perform_on_unit(&j);
 
-                        /* If this unit cannot stopped, then simply wait. */
+                        /* If the unit type does not support starting/stopping,
+                         * then simply wait. */
                         if (r == -EBADR)
                                 r = 0;
                         break;
 
                 case JOB_RELOAD:
-                        r = unit_reload(j->unit);
+                        r = job_perform_on_unit(&j);
                         break;
 
                 case JOB_NOP:
@@ -566,7 +592,6 @@ int job_run_and_invalidate(Job *j) {
                         assert_not_reached("Unknown job type");
         }
 
-        j = manager_get_job(m, id);
         if (j) {
                 if (r == -EALREADY)
                         r = job_finish_and_invalidate(j, JOB_DONE, true);
@@ -588,161 +613,110 @@ int job_run_and_invalidate(Job *j) {
 }
 
 _pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) {
+        const char *format;
         const UnitStatusMessageFormats *format_table;
+        static const char *const generic_finished_start_job[_JOB_RESULT_MAX] = {
+                [JOB_DONE]        = "Started %s.",
+                [JOB_TIMEOUT]     = "Timed out starting %s.",
+                [JOB_FAILED]      = "Failed to start %s.",
+                [JOB_DEPENDENCY]  = "Dependency failed for %s.",
+                [JOB_ASSERT]      = "Assertion failed for %s.",
+                [JOB_UNSUPPORTED] = "Starting of %s not supported.",
+        };
+        static const char *const generic_finished_stop_job[_JOB_RESULT_MAX] = {
+                [JOB_DONE]        = "Stopped %s.",
+                [JOB_FAILED]      = "Stopped (with error) %s.",
+                [JOB_TIMEOUT]     = "Timed out stoppping %s.",
+        };
+        static const char *const generic_finished_reload_job[_JOB_RESULT_MAX] = {
+                [JOB_DONE]        = "Reloaded %s.",
+                [JOB_FAILED]      = "Reload failed for %s.",
+                [JOB_TIMEOUT]     = "Timed out reloading %s.",
+        };
+        /* When verify-active detects the unit is inactive, report it.
+         * Most likely a DEPEND warning from a requisiting unit will
+         * occur next and it's nice to see what was requisited. */
+        static const char *const generic_finished_verify_active_job[_JOB_RESULT_MAX] = {
+                [JOB_SKIPPED]     = "%s is not active.",
+        };
 
         assert(u);
         assert(t >= 0);
         assert(t < _JOB_TYPE_MAX);
 
-        format_table = &UNIT_VTABLE(u)->status_message_formats;
-        if (!format_table)
-                return NULL;
+        if (t == JOB_START || t == JOB_STOP || t == JOB_RESTART) {
+                format_table = &UNIT_VTABLE(u)->status_message_formats;
+                if (format_table) {
+                        format = t == JOB_START ? format_table->finished_start_job[result] :
+                                                  format_table->finished_stop_job[result];
+                        if (format)
+                                return format;
+                }
+        }
 
+        /* Return generic strings */
         if (t == JOB_START)
-                return format_table->finished_start_job[result];
+                return generic_finished_start_job[result];
         else if (t == JOB_STOP || t == JOB_RESTART)
-                return format_table->finished_stop_job[result];
+                return generic_finished_stop_job[result];
+        else if (t == JOB_RELOAD)
+                return generic_finished_reload_job[result];
+        else if (t == JOB_VERIFY_ACTIVE)
+                return generic_finished_verify_active_job[result];
 
         return NULL;
 }
 
-_pure_ static const char *job_get_status_message_format_try_harder(Unit *u, JobType t, JobResult result) {
+static void job_print_status_message(Unit *u, JobType t, JobResult result) {
         const char *format;
+        static const char* const job_result_status_table[_JOB_RESULT_MAX] = {
+                [JOB_DONE]        = ANSI_GREEN_ON            "  OK  " ANSI_HIGHLIGHT_OFF,
+                [JOB_TIMEOUT]     = ANSI_HIGHLIGHT_RED_ON    " TIME " ANSI_HIGHLIGHT_OFF,
+                [JOB_FAILED]      = ANSI_HIGHLIGHT_RED_ON    "FAILED" ANSI_HIGHLIGHT_OFF,
+                [JOB_DEPENDENCY]  = ANSI_HIGHLIGHT_YELLOW_ON "DEPEND" ANSI_HIGHLIGHT_OFF,
+                [JOB_SKIPPED]     = ANSI_HIGHLIGHT_ON        " INFO " ANSI_HIGHLIGHT_OFF,
+                [JOB_ASSERT]      = ANSI_HIGHLIGHT_YELLOW_ON "ASSERT" ANSI_HIGHLIGHT_OFF,
+                [JOB_UNSUPPORTED] = ANSI_HIGHLIGHT_YELLOW_ON "UNSUPP" ANSI_HIGHLIGHT_OFF,
+        };
 
         assert(u);
         assert(t >= 0);
         assert(t < _JOB_TYPE_MAX);
 
         format = job_get_status_message_format(u, t, result);
-        if (format)
-                return format;
-
-        /* Return generic strings */
-        if (t == JOB_START) {
-                if (result == JOB_DONE)
-                        return "Started %s.";
-                else if (result == JOB_TIMEOUT)
-                        return "Timed out starting %s.";
-                else if (result == JOB_FAILED)
-                        return "Failed to start %s.";
-                else if (result == JOB_DEPENDENCY)
-                        return "Dependency failed for %s.";
-                else if (result == JOB_ASSERT)
-                        return "Assertion failed for %s.";
-                else if (result == JOB_UNSUPPORTED)
-                        return "Starting of %s not supported.";
-        } else if (t == JOB_STOP || t == JOB_RESTART) {
-                if (result == JOB_DONE)
-                        return "Stopped %s.";
-                else if (result == JOB_FAILED)
-                        return "Stopped (with error) %s.";
-                else if (result == JOB_TIMEOUT)
-                        return "Timed out stoppping %s.";
-        } else if (t == JOB_RELOAD) {
-                if (result == JOB_DONE)
-                        return "Reloaded %s.";
-                else if (result == JOB_FAILED)
-                        return "Reload failed for %s.";
-                else if (result == JOB_TIMEOUT)
-                        return "Timed out reloading %s.";
-        }
-
-        return NULL;
-}
+        if (!format)
+                return;
 
-static void job_print_status_message(Unit *u, JobType t, JobResult result) {
-        const char *format;
-
-        assert(u);
-        assert(t >= 0);
-        assert(t < _JOB_TYPE_MAX);
+        if (result != JOB_DONE)
+                manager_flip_auto_status(u->manager, true);
 
         DISABLE_WARNING_FORMAT_NONLITERAL;
+        unit_status_printf(u, job_result_status_table[result], format);
+        REENABLE_WARNING;
 
-        if (t == JOB_START) {
-                format = job_get_status_message_format(u, t, result);
-                if (!format)
-                        return;
-
-                switch (result) {
-
-                case JOB_DONE:
-                        if (u->condition_result)
-                                unit_status_printf(u, ANSI_GREEN_ON "  OK  " ANSI_HIGHLIGHT_OFF, format);
-                        break;
-
-                case JOB_TIMEOUT:
-                        manager_flip_auto_status(u->manager, true);
-                        unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format);
-                        break;
-
-                case JOB_FAILED: {
-                        _cleanup_free_ char *quoted = NULL;
-
-                        quoted = shell_maybe_quote(u->id);
-
-                        manager_flip_auto_status(u->manager, true);
-                        unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, format);
-                        manager_status_printf(u->manager, STATUS_TYPE_NORMAL, NULL, "See 'systemctl status %s' for details.", strna(quoted));
-                        break;
-                }
-
-                case JOB_DEPENDENCY:
-                        manager_flip_auto_status(u->manager, true);
-                        unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "DEPEND" ANSI_HIGHLIGHT_OFF, format);
-                        break;
-
-                case JOB_ASSERT:
-                        manager_flip_auto_status(u->manager, true);
-                        unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "ASSERT" ANSI_HIGHLIGHT_OFF, format);
-                        break;
-
-                case JOB_UNSUPPORTED:
-                        manager_flip_auto_status(u->manager, true);
-                        unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "UNSUPP" ANSI_HIGHLIGHT_OFF, format);
-                        break;
-
-                default:
-                        ;
-                }
-
-        } else if (t == JOB_STOP || t == JOB_RESTART) {
-
-                format = job_get_status_message_format(u, t, result);
-                if (!format)
-                        return;
-
-                switch (result) {
-
-                case JOB_TIMEOUT:
-                        manager_flip_auto_status(u->manager, true);
-                        unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format);
-                        break;
-
-                case JOB_DONE:
-                case JOB_FAILED:
-                        unit_status_printf(u, ANSI_GREEN_ON "  OK  " ANSI_HIGHLIGHT_OFF, format);
-                        break;
-
-                default:
-                        ;
-                }
-
-        } else if (t == JOB_VERIFY_ACTIVE) {
+        if (t == JOB_START && result == JOB_FAILED) {
+                _cleanup_free_ char *quoted = shell_maybe_quote(u->id);
 
-                /* When verify-active detects the unit is inactive, report it.
-                 * Most likely a DEPEND warning from a requisiting unit will
-                 * occur next and it's nice to see what was requisited. */
-                if (result == JOB_SKIPPED)
-                        unit_status_printf(u, ANSI_HIGHLIGHT_ON " INFO " ANSI_HIGHLIGHT_OFF, "%s is not active.");
+                manager_status_printf(u->manager, STATUS_TYPE_NORMAL, NULL,
+                                      "See 'systemctl status %s' for details.", strna(quoted));
         }
-
-        REENABLE_WARNING;
 }
 
 static void job_log_status_message(Unit *u, JobType t, JobResult result) {
         const char *format;
         char buf[LINE_MAX];
+        sd_id128_t mid;
+        static const int job_result_log_level[_JOB_RESULT_MAX] = {
+                [JOB_DONE]        = LOG_INFO,
+                [JOB_CANCELED]    = LOG_INFO,
+                [JOB_TIMEOUT]     = LOG_ERR,
+                [JOB_FAILED]      = LOG_ERR,
+                [JOB_DEPENDENCY]  = LOG_WARNING,
+                [JOB_SKIPPED]     = LOG_NOTICE,
+                [JOB_INVALID]     = LOG_INFO,
+                [JOB_ASSERT]      = LOG_WARNING,
+                [JOB_UNSUPPORTED] = LOG_WARNING,
+        };
 
         assert(u);
         assert(t >= 0);
@@ -754,7 +728,7 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) {
         if (log_on_console())
                 return;
 
-        format = job_get_status_message_format_try_harder(u, t, result);
+        format = job_get_status_message_format(u, t, result);
         if (!format)
                 return;
 
@@ -762,32 +736,40 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) {
         snprintf(buf, sizeof(buf), format, unit_description(u));
         REENABLE_WARNING;
 
-        if (t == JOB_START) {
-                sd_id128_t mid;
-
+        if (t == JOB_START)
                 mid = result == JOB_DONE ? SD_MESSAGE_UNIT_STARTED : SD_MESSAGE_UNIT_FAILED;
-                log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
-                           LOG_MESSAGE_ID(mid),
+        else if (t == JOB_STOP || t == JOB_RESTART)
+                mid = SD_MESSAGE_UNIT_STOPPED;
+        else if (t == JOB_RELOAD)
+                mid = SD_MESSAGE_UNIT_RELOADED;
+        else {
+                log_struct(job_result_log_level[result],
                            LOG_UNIT_ID(u),
                            LOG_MESSAGE("%s", buf),
                            "RESULT=%s", job_result_to_string(result),
                            NULL);
+                return;
+        }
 
-        } else if (t == JOB_STOP)
-                log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
-                           LOG_MESSAGE_ID(SD_MESSAGE_UNIT_STOPPED),
-                           LOG_UNIT_ID(u),
-                           LOG_MESSAGE("%s", buf),
-                           "RESULT=%s", job_result_to_string(result),
-                           NULL);
+        log_struct(job_result_log_level[result],
+                   LOG_MESSAGE_ID(mid),
+                   LOG_UNIT_ID(u),
+                   LOG_MESSAGE("%s", buf),
+                   "RESULT=%s", job_result_to_string(result),
+                   NULL);
+}
 
-        else if (t == JOB_RELOAD)
-                log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
-                           LOG_MESSAGE_ID(SD_MESSAGE_UNIT_RELOADED),
-                           LOG_UNIT_ID(u),
-                           LOG_MESSAGE("%s", buf),
-                           "RESULT=%s", job_result_to_string(result),
-                           NULL);
+static void job_emit_status_message(Unit *u, JobType t, JobResult result) {
+
+        /* No message if the job did not actually do anything due to failed condition. */
+        if (t == JOB_START && result == JOB_DONE && !u->condition_result)
+                return;
+
+        job_log_status_message(u, t, result);
+
+        /* Reload status messages have traditionally not been printed to console. */
+        if (t != JOB_RELOAD)
+                job_print_status_message(u, t, result);
 }
 
 static void job_fail_dependencies(Unit *u, UnitDependency d) {
@@ -825,8 +807,7 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
 
         log_unit_debug(u, "Job %s/%s finished, result=%s", u->id, job_type_to_string(t), job_result_to_string(result));
 
-        job_print_status_message(u, t, result);
-        job_log_status_message(u, t, result);
+        job_emit_status_message(u, t, result);
 
         job_add_to_dbus_queue(j);
 
index 851b41351e666969a28d40590ae3b7bd30df3a42..bf8e52bf0e9c14d9c8d80656aeea46979bc3c543 100644 (file)
@@ -1025,7 +1025,7 @@ static int mount_reload(Unit *u) {
         assert(m->state == MOUNT_MOUNTED);
 
         mount_enter_remounting(m);
-        return 0;
+        return 1;
 }
 
 static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
@@ -1897,7 +1897,6 @@ const UnitVTable mount_vtable = {
                 .finished_start_job = {
                         [JOB_DONE]       = "Mounted %s.",
                         [JOB_FAILED]     = "Failed to mount %s.",
-                        [JOB_DEPENDENCY] = "Dependency failed for %s.",
                         [JOB_TIMEOUT]    = "Timed out mounting %s.",
                 },
                 .finished_stop_job = {
index d72ff54daa37a2b345aec9c915e9c0eab66ced97..39a2507b6f875b9b543608576d99b700ed04e2ec 100644 (file)
@@ -1974,7 +1974,7 @@ static int service_reload(Unit *u) {
         assert(s->state == SERVICE_RUNNING || s->state == SERVICE_EXITED);
 
         service_enter_reload(s);
-        return 0;
+        return 1;
 }
 
 _pure_ static bool service_can_reload(Unit *u) {
@@ -3229,13 +3229,10 @@ const UnitVTable service_vtable = {
                 .finished_start_job = {
                         [JOB_DONE]       = "Started %s.",
                         [JOB_FAILED]     = "Failed to start %s.",
-                        [JOB_DEPENDENCY] = "Dependency failed for %s.",
-                        [JOB_TIMEOUT]    = "Timed out starting %s.",
                 },
                 .finished_stop_job = {
                         [JOB_DONE]       = "Stopped %s.",
                         [JOB_FAILED]     = "Stopped (with error) %s.",
-                        [JOB_TIMEOUT]    = "Timed out stopping %s.",
                 },
         },
 };
index e52bf715154aa17d5baa93aa45a72c82d254f3d1..064eb5d93327b5cda413982c6dfb415a76fd5ff8 100644 (file)
@@ -297,7 +297,6 @@ const UnitVTable slice_vtable = {
         .status_message_formats = {
                 .finished_start_job = {
                         [JOB_DONE]       = "Created slice %s.",
-                        [JOB_DEPENDENCY] = "Dependency failed for %s.",
                 },
                 .finished_stop_job = {
                         [JOB_DONE]       = "Removed slice %s.",
index 693cbc60800b32f6145d2a6fa45cafeaa37efacc..87631f8753ac857db7929f73ef256aa2511d7430 100644 (file)
@@ -2722,7 +2722,6 @@ const UnitVTable socket_vtable = {
                 .finished_start_job = {
                         [JOB_DONE]       = "Listening on %s.",
                         [JOB_FAILED]     = "Failed to listen on %s.",
-                        [JOB_DEPENDENCY] = "Dependency failed for %s.",
                         [JOB_TIMEOUT]    = "Timed out starting %s.",
                 },
                 .finished_stop_job = {
index 193c8c37675811552620bf2f7c6c88c6b44991f4..0bc3827ff061542490cb474f0c38e538a506dbdf 100644 (file)
@@ -1505,7 +1505,6 @@ const UnitVTable swap_vtable = {
                 .finished_start_job = {
                         [JOB_DONE]       = "Activated swap %s.",
                         [JOB_FAILED]     = "Failed to activate swap %s.",
-                        [JOB_DEPENDENCY] = "Dependency failed for %s.",
                         [JOB_TIMEOUT]    = "Timed out activating swap %s.",
                 },
                 .finished_stop_job = {
index 8817ef21c4c61a3daba8d24b717e9a3c19f83406..b492a7c4c7f046c50d76f16ef18258f1eaabee27 100644 (file)
@@ -227,7 +227,6 @@ const UnitVTable target_vtable = {
         .status_message_formats = {
                 .finished_start_job = {
                         [JOB_DONE]       = "Reached target %s.",
-                        [JOB_DEPENDENCY] = "Dependency failed for %s.",
                 },
                 .finished_stop_job = {
                         [JOB_DONE]       = "Stopped target %s.",
index fac017c57d90eb43cbc16a29f08d60739b9d3c9d..dd5e80128512766ce2b6c133bcd1127155e49d08 100644 (file)
@@ -1318,42 +1318,28 @@ static bool unit_assert_test(Unit *u) {
 }
 
 _pure_ static const char* unit_get_status_message_format(Unit *u, JobType t) {
-        const UnitStatusMessageFormats *format_table;
-
-        assert(u);
-        assert(t >= 0);
-        assert(t < _JOB_TYPE_MAX);
-
-        if (t != JOB_START && t != JOB_STOP)
-                return NULL;
-
-        format_table = &UNIT_VTABLE(u)->status_message_formats;
-        if (!format_table)
-                return NULL;
-
-        return format_table->starting_stopping[t == JOB_STOP];
-}
-
-_pure_ static const char *unit_get_status_message_format_try_harder(Unit *u, JobType t) {
         const char *format;
+        const UnitStatusMessageFormats *format_table;
 
         assert(u);
-        assert(t >= 0);
-        assert(t < _JOB_TYPE_MAX);
+        assert(t == JOB_START || t == JOB_STOP || t == JOB_RELOAD);
 
-        format = unit_get_status_message_format(u, t);
-        if (format)
-                return format;
+        if (t != JOB_RELOAD) {
+                format_table = &UNIT_VTABLE(u)->status_message_formats;
+                if (format_table) {
+                        format = format_table->starting_stopping[t == JOB_STOP];
+                        if (format)
+                                return format;
+                }
+        }
 
         /* Return generic strings */
         if (t == JOB_START)
                 return "Starting %s.";
         else if (t == JOB_STOP)
                 return "Stopping %s.";
-        else if (t == JOB_RELOAD)
+        else
                 return "Reloading %s.";
-
-        return NULL;
 }
 
 static void unit_status_print_starting_stopping(Unit *u, JobType t) {
@@ -1361,12 +1347,7 @@ static void unit_status_print_starting_stopping(Unit *u, JobType t) {
 
         assert(u);
 
-        /* We only print status messages for selected units on
-         * selected operations. */
-
         format = unit_get_status_message_format(u, t);
-        if (!format)
-                return;
 
         DISABLE_WARNING_FORMAT_NONLITERAL;
         unit_status_printf(u, "", format);
@@ -1388,9 +1369,7 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) {
 
         /* We log status messages for all units and all operations. */
 
-        format = unit_get_status_message_format_try_harder(u, t);
-        if (!format)
-                return;
+        format = unit_get_status_message_format(u, t);
 
         DISABLE_WARNING_FORMAT_NONLITERAL;
         snprintf(buf, sizeof(buf), format, unit_description(u));
@@ -1413,6 +1392,15 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) {
                    NULL);
 }
 
+void unit_status_emit_starting_stopping_reloading(Unit *u, JobType t) {
+
+        unit_status_log_starting_stopping_reloading(u, t);
+
+        /* Reload status messages have traditionally not been printed to console. */
+        if (t != JOB_RELOAD)
+                unit_status_print_starting_stopping(u, t);
+}
+
 /* Errors:
  *         -EBADR:     This unit type does not support starting.
  *         -EALREADY:  Unit is already started.
@@ -1423,7 +1411,6 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) {
 int unit_start(Unit *u) {
         UnitActiveState state;
         Unit *following;
-        int r;
 
         assert(u);
 
@@ -1477,14 +1464,7 @@ int unit_start(Unit *u) {
 
         unit_add_to_dbus_queue(u);
 
-        r = UNIT_VTABLE(u)->start(u);
-        if (r <= 0)
-                return r;
-
-        /* Log if the start function actually did something */
-        unit_status_log_starting_stopping_reloading(u, JOB_START);
-        unit_status_print_starting_stopping(u, JOB_START);
-        return r;
+        return UNIT_VTABLE(u)->start(u);
 }
 
 bool unit_can_start(Unit *u) {
@@ -1508,7 +1488,6 @@ bool unit_can_isolate(Unit *u) {
 int unit_stop(Unit *u) {
         UnitActiveState state;
         Unit *following;
-        int r;
 
         assert(u);
 
@@ -1527,13 +1506,7 @@ int unit_stop(Unit *u) {
 
         unit_add_to_dbus_queue(u);
 
-        r = UNIT_VTABLE(u)->stop(u);
-        if (r <= 0)
-                return r;
-
-        unit_status_log_starting_stopping_reloading(u, JOB_STOP);
-        unit_status_print_starting_stopping(u, JOB_STOP);
-        return r;
+        return UNIT_VTABLE(u)->stop(u);
 }
 
 /* Errors:
@@ -1544,7 +1517,6 @@ int unit_stop(Unit *u) {
 int unit_reload(Unit *u) {
         UnitActiveState state;
         Unit *following;
-        int r;
 
         assert(u);
 
@@ -1571,12 +1543,7 @@ int unit_reload(Unit *u) {
 
         unit_add_to_dbus_queue(u);
 
-        r = UNIT_VTABLE(u)->reload(u);
-        if (r <= 0)
-                return r;
-
-        unit_status_log_starting_stopping_reloading(u, JOB_RELOAD);
-        return r;
+        return UNIT_VTABLE(u)->reload(u);
 }
 
 bool unit_can_reload(Unit *u) {
index 9491ef64f9c36367c303d26d3b0c08eebf585a3c..e60168267f0eab84f51f537fb4496c8e13ca3f85 100644 (file)
@@ -544,6 +544,7 @@ int unit_add_node_link(Unit *u, const char *what, bool wants);
 int unit_coldplug(Unit *u);
 
 void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg_format) _printf_(3, 0);
+void unit_status_emit_starting_stopping_reloading(Unit *u, JobType t);
 
 bool unit_need_daemon_reload(Unit *u);
 
index 99115d5e492f4157ee3722bc51a4e60131d63b8a..c53666ddd02f396ba41b4672d25cf770446e6c37 100644 (file)
@@ -1131,7 +1131,7 @@ static int add_name_change_match(sd_bus *bus,
 
                 /* If the old name is unset or empty, then
                  * this can match against added names */
-                if (!old_owner || old_owner[0] == 0) {
+                if (isempty(old_owner)) {
                         item->type = KDBUS_ITEM_NAME_ADD;
 
                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
@@ -1141,7 +1141,7 @@ static int add_name_change_match(sd_bus *bus,
 
                 /* If the new name is unset or empty, then
                  * this can match against removed names */
-                if (!new_owner || new_owner[0] == 0) {
+                if (isempty(new_owner)) {
                         item->type = KDBUS_ITEM_NAME_REMOVE;
 
                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
@@ -1185,7 +1185,7 @@ static int add_name_change_match(sd_bus *bus,
 
                 /* If the old name is unset or empty, then this can
                  * match against added ids */
-                if (!old_owner || old_owner[0] == 0) {
+                if (isempty(old_owner)) {
                         item->type = KDBUS_ITEM_ID_ADD;
                         if (!isempty(new_owner))
                                 item->id_change.id = new_owner_id;
@@ -1197,7 +1197,7 @@ static int add_name_change_match(sd_bus *bus,
 
                 /* If thew new name is unset or empty, then this can
                  * match against removed ids */
-                if (!new_owner || new_owner[0] == 0) {
+                if (isempty(new_owner)) {
                         item->type = KDBUS_ITEM_ID_REMOVE;
                         if (!isempty(old_owner))
                                 item->id_change.id = old_owner_id;
index 74ac2ab344d7f271a831b24a8f0e6175b98a2797..8c6fd8ad30fa275237a42fc510256ba2d9604f67 100644 (file)
@@ -196,19 +196,29 @@ static const NLType rtnl_link_info_data_iptun_types[IFLA_IPTUN_MAX + 1] = {
         [IFLA_IPTUN_6RD_RELAY_PREFIX]    = { .type = NETLINK_TYPE_U32 },
         [IFLA_IPTUN_6RD_PREFIXLEN]       = { .type = NETLINK_TYPE_U16 },
         [IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NETLINK_TYPE_U16 },
+        [IFLA_IPTUN_ENCAP_TYPE]          = { .type = NETLINK_TYPE_U16},
+        [IFLA_IPTUN_ENCAP_FLAGS]         = { .type = NETLINK_TYPE_U16},
+        [IFLA_IPTUN_ENCAP_SPORT]         = { .type = NETLINK_TYPE_U16},
+        [IFLA_IPTUN_ENCAP_DPORT]         = { .type = NETLINK_TYPE_U16},
 };
 
 static  const NLType rtnl_link_info_data_ipgre_types[IFLA_GRE_MAX + 1] = {
-        [IFLA_GRE_LINK]     = { .type = NETLINK_TYPE_U32 },
-        [IFLA_GRE_IFLAGS]   = { .type = NETLINK_TYPE_U16 },
-        [IFLA_GRE_OFLAGS]   = { .type = NETLINK_TYPE_U16 },
-        [IFLA_GRE_IKEY]     = { .type = NETLINK_TYPE_U32 },
-        [IFLA_GRE_OKEY]     = { .type = NETLINK_TYPE_U32 },
-        [IFLA_GRE_LOCAL]    = { .type = NETLINK_TYPE_IN_ADDR },
-        [IFLA_GRE_REMOTE]   = { .type = NETLINK_TYPE_IN_ADDR },
-        [IFLA_GRE_TTL]      = { .type = NETLINK_TYPE_U8 },
-        [IFLA_GRE_TOS]      = { .type = NETLINK_TYPE_U8 },
-        [IFLA_GRE_PMTUDISC] = { .type = NETLINK_TYPE_U8 },
+        [IFLA_GRE_LINK]         = { .type = NETLINK_TYPE_U32 },
+        [IFLA_GRE_IFLAGS]       = { .type = NETLINK_TYPE_U16 },
+        [IFLA_GRE_OFLAGS]       = { .type = NETLINK_TYPE_U16 },
+        [IFLA_GRE_IKEY]         = { .type = NETLINK_TYPE_U32 },
+        [IFLA_GRE_OKEY]         = { .type = NETLINK_TYPE_U32 },
+        [IFLA_GRE_LOCAL]        = { .type = NETLINK_TYPE_IN_ADDR },
+        [IFLA_GRE_REMOTE]       = { .type = NETLINK_TYPE_IN_ADDR },
+        [IFLA_GRE_TTL]          = { .type = NETLINK_TYPE_U8 },
+        [IFLA_GRE_TOS]          = { .type = NETLINK_TYPE_U8 },
+        [IFLA_GRE_PMTUDISC]     = { .type = NETLINK_TYPE_U8 },
+        [IFLA_GRE_FLOWINFO]     = { .type = NETLINK_TYPE_U32 },
+        [IFLA_GRE_FLAGS]        = { .type = NETLINK_TYPE_U32 },
+        [IFLA_GRE_ENCAP_TYPE]   = { .type = NETLINK_TYPE_U16 },
+        [IFLA_GRE_ENCAP_FLAGS]  = { .type = NETLINK_TYPE_U16 },
+        [IFLA_GRE_ENCAP_SPORT]  = { .type = NETLINK_TYPE_U16 },
+        [IFLA_GRE_ENCAP_DPORT]  = { .type = NETLINK_TYPE_U16 },
 };
 
 static const NLType rtnl_link_info_data_ipvti_types[IFLA_VTI_MAX + 1] = {
index 049e33e2a6b48f61a5f2c8b35f12411ebe628e3e..e6371ff04d9a323e4af123047097c02e94102be0 100644 (file)
@@ -1774,7 +1774,7 @@ static int nologin_timeout_handler(
 
         log_info("Creating /run/nologin, blocking further logins...");
 
-        r = write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_ATOMIC);
+        r = write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
         if (r < 0)
                 log_error_errno(r, "Failed to create /run/nologin: %m");
         else
index d446bfa8b3fdb4d929ab0969f823167fe0b73499..4aa301b112a4afbda50b81f65ffd19d510e1ba18 100644 (file)
@@ -270,12 +270,18 @@ static int dhcp_lease_lost(Link *link) {
         if (link->network->dhcp_hostname) {
                 const char *hostname = NULL;
 
-                r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
-                if (r >= 0 && hostname) {
-                        r = link_set_hostname(link, "");
+                if (!link->network->hostname)
+                        r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
+                else
+                        hostname = link->network->hostname;
+
+                if (r >= 0 || hostname) {
+                        r = link_set_hostname(link, hostname);
                         if (r < 0)
-                                log_link_error(link,
-                                               "Failed to reset transient hostname");
+                                log_link_error_errno(link, r,
+                                                     "Failed to set transient hostname to '%s': %m",
+                                                     hostname);
+
                 }
         }
 
@@ -464,8 +470,12 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
         if (link->network->dhcp_hostname) {
                 const char *hostname;
 
-                r = sd_dhcp_lease_get_hostname(lease, &hostname);
-                if (r >= 0) {
+                if (!link->network->hostname)
+                        r = sd_dhcp_lease_get_hostname(lease, &hostname);
+                else
+                        hostname = link->network->hostname;
+
+                if (r >= 0 || hostname) {
                         r = link_set_hostname(link, hostname);
                         if (r < 0)
                                 log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname);
@@ -616,14 +626,19 @@ int dhcp4_configure(Link *link) {
 
         if (link->network->dhcp_sendhost) {
                 _cleanup_free_ char *hostname = NULL;
+                const char *hn = NULL;
+
+                if (!link->network->hostname)  {
+                        hostname = gethostname_malloc();
+                        if (!hostname)
+                                return -ENOMEM;
 
-                hostname = gethostname_malloc();
-                if (!hostname)
-                        return -ENOMEM;
+                        hn = hostname;
+                } else
+                        hn = link->network->hostname;
 
-                if (!is_localhost(hostname)) {
-                        r = sd_dhcp_client_set_hostname(link->dhcp_client,
-                                                        hostname);
+                if (!is_localhost(hn)) {
+                        r = sd_dhcp_client_set_hostname(link->dhcp_client, hn);
                         if (r < 0)
                                 return r;
                 }
index 010c106610f4ea581478f524b3771bca848dfb66..63258c03762eaf5a4aa46c3eeb3fd4e0bc23ef18 100644 (file)
@@ -36,6 +36,7 @@ Tunnel.TOS,                  config_parse_unsigned,              0,
 Tunnel.TTL,                  config_parse_unsigned,              0,                             offsetof(Tunnel, ttl)
 Tunnel.DiscoverPathMTU,      config_parse_bool,                  0,                             offsetof(Tunnel, pmtudisc)
 Tunnel.Mode,                 config_parse_ip6tnl_mode,           0,                             offsetof(Tunnel, ip6tnl_mode)
+Tunnel.IPv6FlowLabel,        config_parse_ipv6_flowlabel,        0,                             offsetof(Tunnel, ipv6_flowlabel)
 Peer.Name,                   config_parse_ifname,                0,                             offsetof(Veth, ifname_peer)
 Peer.MACAddress,             config_parse_hwaddr,                0,                             offsetof(Veth, mac_peer)
 VXLAN.Id,                    config_parse_uint64,                0,                             offsetof(VxLan, id)
index 5533fb5c7bb8b65cfc5fe47f01e4b456a56d5a7d..a13edf693602106ad3eb4043731f338ebcbea7b2 100644 (file)
@@ -33,6 +33,7 @@
 #include "conf-parser.h"
 
 #define DEFAULT_TNL_HOP_LIMIT   64
+#define IP6_FLOWINFO_FLOWLABEL  htonl(0x000FFFFF)
 
 static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = {
         [NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6",
@@ -264,6 +265,16 @@ static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netl
         if (r < 0)
                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
 
+        if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) {
+                r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLOWINFO, t->ipv6_flowlabel);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLOWINFO attribute: %m");
+        }
+
+        r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLAGS, t->flags);
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLAGS attribute: %m");
+
         switch (t->ip6tnl_mode) {
         case NETDEV_IP6_TNL_MODE_IP6IP6:
                 proto = IPPROTO_IPV6;
@@ -380,6 +391,52 @@ int config_parse_tunnel_address(const char *unit,
         return 0;
 }
 
+static const char* const ipv6_flowlabel_table[_NETDEV_IPV6_FLOWLABEL_MAX] = {
+        [NETDEV_IPV6_FLOWLABEL_INHERIT] = "inherit",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(ipv6_flowlabel, IPv6FlowLabel);
+
+int config_parse_ipv6_flowlabel(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) {
+        IPv6FlowLabel *ipv6_flowlabel = data;
+        Tunnel *t = userdata;
+        IPv6FlowLabel s;
+        int k = 0;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(ipv6_flowlabel);
+
+        s = ipv6_flowlabel_from_string(rvalue);
+        if (s != _NETDEV_IPV6_FLOWLABEL_INVALID) {
+                *ipv6_flowlabel = IP6_FLOWINFO_FLOWLABEL;
+                t->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL;
+        } else {
+                r = config_parse_unsigned(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &k, userdata);
+                if (r >= 0) {
+                        if (k > 0xFFFFF)
+                                log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse IPv6 flowlabel option, ignoring: %s", rvalue);
+                        else {
+                                *ipv6_flowlabel = htonl(k) & IP6_FLOWINFO_FLOWLABEL;
+                                t->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL;
+                        }
+                }
+        }
+
+        return 0;
+}
+
 static void ipip_init(NetDev *n) {
         Tunnel *t = IPIP(n);
 
@@ -452,6 +509,7 @@ static void ip6tnl_init(NetDev *n) {
         t->ttl = DEFAULT_TNL_HOP_LIMIT;
         t->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
         t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID;
+        t->ipv6_flowlabel = _NETDEV_IPV6_FLOWLABEL_INVALID;
 }
 
 const NetDevVTable ipip_vtable = {
index 546c9f08b9b1f2ad746098b3f1cb9bf05f106f1d..47981fbe32421b5381f4bfd3a1e42161dbec73a9 100644 (file)
@@ -33,6 +33,12 @@ typedef enum Ip6TnlMode {
         _NETDEV_IP6_TNL_MODE_INVALID = -1,
 } Ip6TnlMode;
 
+typedef enum IPv6FlowLabel {
+        NETDEV_IPV6_FLOWLABEL_INHERIT = 0xFFFFF + 1,
+        _NETDEV_IPV6_FLOWLABEL_MAX,
+        _NETDEV_IPV6_FLOWLABEL_INVALID = -1,
+} IPv6FlowLabel;
+
 struct Tunnel {
         NetDev meta;
 
@@ -48,6 +54,7 @@ struct Tunnel {
         union in_addr_union remote;
 
         Ip6TnlMode ip6tnl_mode;
+        IPv6FlowLabel ipv6_flowlabel;
 
         bool pmtudisc;
 };
@@ -81,3 +88,12 @@ int config_parse_tunnel_address(const char *unit,
                                 const char *rvalue,
                                 void *data,
                                 void *userdata);
+
+const char *ipv6_flowlabel_to_string(IPv6FlowLabel d) _const_;
+IPv6FlowLabel ipv6_flowlabel_from_string(const char *d) _pure_;
+
+int config_parse_ipv6_flowlabel(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);
index 787fc2ff5bec1c05e163cc3b362954cc8328efcf..3a78c3d8a89abee280a702dabb3cd637bbcfab57 100644 (file)
@@ -67,6 +67,7 @@ DHCP.UseHostname,              config_parse_bool,                              0
 DHCP.UseDomains,               config_parse_bool,                              0,                             offsetof(Network, dhcp_domains)
 DHCP.UseRoutes,                config_parse_bool,                              0,                             offsetof(Network, dhcp_routes)
 DHCP.SendHostname,             config_parse_bool,                              0,                             offsetof(Network, dhcp_sendhost)
+DHCP.Hostname,                 config_parse_hostname,                          0,                             offsetof(Network, hostname)
 DHCP.RequestBroadcast,         config_parse_bool,                              0,                             offsetof(Network, dhcp_broadcast)
 DHCP.CriticalConnection,       config_parse_bool,                              0,                             offsetof(Network, dhcp_critical)
 DHCP.VendorClassIdentifier,    config_parse_string,                            0,                             offsetof(Network, dhcp_vendor_class_identifier)
index a8e9ef909c3eb20df33ff387ba410708250f8c5f..55e735e6bf44b792a84fa471d83b762caee779be 100644 (file)
@@ -207,6 +207,7 @@ void network_free(Network *network) {
 
         free(network->description);
         free(network->dhcp_vendor_class_identifier);
+        free(network->hostname);
 
         free(network->mac);
 
@@ -809,3 +810,38 @@ int config_parse_ipv6_privacy_extensions(
 
         return 0;
 }
+
+int config_parse_hostname(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) {
+        char **hostname = data;
+        char *hn = NULL;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+
+        r = config_parse_string(unit, filename, line, section, section_line,
+                                lvalue, ltype, rvalue, &hn, userdata);
+        if (r < 0)
+                return r;
+
+        if (!hostname_is_valid(hn)) {
+                log_syntax(unit, LOG_ERR, filename, line, EINVAL, "hostname is not valid, ignoring assignment: %s", rvalue);
+
+                free(hn);
+                return 0;
+        }
+
+        *hostname = hn;
+
+        return 0;
+}
index 81273a8786cc8e4464c3e0efd1f396bb02764ca4..fb95f90169d76ca2a259dcf760a25ee07602ecce 100644 (file)
@@ -133,6 +133,7 @@ struct Network {
         AddressFamilyBoolean dhcp;
         DCHPClientIdentifier dhcp_client_identifier;
         char *dhcp_vendor_class_identifier;
+        char *hostname;
         bool dhcp_dns;
         bool dhcp_ntp;
         bool dhcp_mtu;
@@ -451,3 +452,7 @@ const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_;
 IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_;
 
 int config_parse_ipv6_privacy_extensions(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);
+
+
+/* Hostname */
+int config_parse_hostname(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);
index 7ba0b7fc8f2048e171feaf8eb46f1617424fe6c0..a59d4c6d507681d7a479e131d50571a2e5e48598 100644 (file)
@@ -638,10 +638,20 @@ int main(int argc, char *argv[])
                  * All other values are reserved.
                  */
                 word = identify.wyde[108];
-                if ((word & 0xf000) == 0x5000)
+                if ((word & 0xf000) == 0x5000) {
+                        uint64_t wwwn;
+
+                        wwwn   = identify.wyde[108];
+                        wwwn <<= 16;
+                        wwwn  |= identify.wyde[109];
+                        wwwn <<= 16;
+                        wwwn  |= identify.wyde[110];
+                        wwwn <<= 16;
+                        wwwn  |= identify.wyde[111];
                         printf("ID_WWN=0x%1$" PRIx64 "\n"
                                "ID_WWN_WITH_EXTENSION=0x%1$" PRIx64 "\n",
-                               identify.octa[108/4]);
+                               wwwn);
+                }
 
                 /* from Linux's include/linux/ata.h */
                 if (identify.wyde[0] == 0x848a ||
index 0661f7be00fc50c3d62643e572c48816342ba1e1..945845d72c04d73bb5bd649c5d8130609db54bd7 100644 (file)
@@ -1358,6 +1358,7 @@ static int listen_fds(int *rctrl, int *rnetlink) {
  *   udev.event-timeout=<number of seconds>    seconds to wait before terminating an event
  */
 static int parse_proc_cmdline_item(const char *key, const char *value) {
+        const char *full_key = key;
         int r;
 
         assert(key);
@@ -1377,25 +1378,28 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
                 int prio;
 
                 prio = util_log_priority(value);
+                if (prio < 0)
+                        goto invalid;
                 log_set_max_level(prio);
         } else if (streq(key, "children-max")) {
                 r = safe_atou(value, &arg_children_max);
                 if (r < 0)
-                        log_warning("invalid udev.children-max ignored: %s", value);
+                        goto invalid;
         } else if (streq(key, "exec-delay")) {
                 r = safe_atoi(value, &arg_exec_delay);
                 if (r < 0)
-                        log_warning("invalid udev.exec-delay ignored: %s", value);
+                        goto invalid;
         } else if (streq(key, "event-timeout")) {
                 r = safe_atou64(value, &arg_event_timeout_usec);
                 if (r < 0)
-                        log_warning("invalid udev.event-timeout ignored: %s", value);
-                else {
-                        arg_event_timeout_usec *= USEC_PER_SEC;
-                        arg_event_timeout_warn_usec = (arg_event_timeout_usec / 3) ? : 1;
-                }
+                        goto invalid;
+                arg_event_timeout_usec *= USEC_PER_SEC;
+                arg_event_timeout_warn_usec = (arg_event_timeout_usec / 3) ? : 1;
         }
 
+        return 0;
+invalid:
+        log_warning("invalid %s ignored: %s", full_key, value);
         return 0;
 }
 
index ddeb310c3c9d2093ff034524d8b1cce06b50a8ef..e80a7771de6ae63d24bf65cc71aceedd08d8a935 100644 (file)
@@ -65,7 +65,7 @@ int main(int argc, char*argv[]) {
         } else if (streq(argv[1], "stop")) {
                 int r;
 
-                r = write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_ATOMIC);
+                r = write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
                 if (r < 0) {
                         log_error_errno(r, "Failed to create /run/nologin: %m");
                         return EXIT_FAILURE;