]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #14472 from poettering/test-43-fixes
authorAnita Zhang <the.anitazha@gmail.com>
Tue, 7 Jan 2020 18:53:13 +0000 (10:53 -0800)
committerGitHub <noreply@github.com>
Tue, 7 Jan 2020 18:53:13 +0000 (10:53 -0800)
Various robustness fixes for TEST-43-PRIVATEUSER-UNPRIV

29 files changed:
man/systemd-networkd-wait-online.service.xml
man/systemd.network.xml
src/basic/locale-util.c
src/basic/locale-util.h
src/basic/virt.c
src/libsystemd/sd-netlink/netlink-util.c
src/libsystemd/sd-netlink/netlink-util.h
src/libsystemd/sd-netlink/rtnl-message.c
src/network/meson.build
src/network/networkd-dhcp4.c
src/network/networkd-link.c
src/network/networkd-manager.c
src/network/networkd-ndisc.c
src/network/networkd-route.c
src/network/networkd-route.h
src/nspawn/nspawn-mount.c
src/nspawn/nspawn-mount.h
src/nspawn/nspawn-network.c
src/nspawn/nspawn.c
src/shared/pkcs11-util.c
src/test/test-locale-util.c
src/udev/udev-rules.c
test/test-network/conf/dhcp-client-gateway-ipv4.network [new file with mode: 0644]
test/test-network/conf/dhcp-client-gateway-ipv6.network [new file with mode: 0644]
test/test-network/systemd-networkd-tests.py
units/meson.build
units/modprobe@.service [new file with mode: 0644]
units/systemd-logind.service.in
units/systemd-nspawn@.service.in

index 51b865dc0b1ecf9da350c4cfb9af8c0b6ed51864..96fcb5fb48e3c58b125549a23ddf58f4f2b7793d 100644 (file)
@@ -97,7 +97,7 @@
       </varlistentry>
 
       <varlistentry>
-        <term><option>--timeout=</option> <replaceable>SECS</replaceable></term>
+        <term><option>--timeout=</option><replaceable>SECS</replaceable></term>
 
         <listitem><para>Fail the service if the network is not online
         by the time the timeout elapses. A timeout of 0 disables the
index 4cd25201737f2638c38c9cdb12017f6ae376422f..4299583fe7e1810a69c663afe0572394fda2e1c8 100644 (file)
         <varlistentry>
           <term><varname>Gateway=</varname></term>
           <listitem>
-            <para>As in the <literal>[Network]</literal> section.</para>
+            <para>Takes the gateway address or special value <literal>dhcp</literal>. If
+            <literal>dhcp</literal>, then the gateway address provided by DHCP (or in the IPv6 case,
+            provided by IPv6 RA) is used.</para>
           </listitem>
         </varlistentry>
          <varlistentry>
index 457280df9fe7d479d90f92f7fdd3cb2fb9acef85..dc625119355f7c3e042f32d47d8acf05100f7bd3 100644 (file)
@@ -342,12 +342,11 @@ const char *special_glyph(SpecialGlyph code) {
                         [SPECIAL_GLYPH_TRIANGULAR_BULLET]       = ">",
                         [SPECIAL_GLYPH_BLACK_CIRCLE]            = "*",
                         [SPECIAL_GLYPH_BULLET]                  = "*",
-                        [SPECIAL_GLYPH_ARROW]                   = "->",
-                        [SPECIAL_GLYPH_MDASH]                   = "-",
-                        [SPECIAL_GLYPH_ELLIPSIS]                = "...",
                         [SPECIAL_GLYPH_MU]                      = "u",
                         [SPECIAL_GLYPH_CHECK_MARK]              = "+",
                         [SPECIAL_GLYPH_CROSS_MARK]              = "-",
+                        [SPECIAL_GLYPH_ARROW]                   = "->",
+                        [SPECIAL_GLYPH_ELLIPSIS]                = "...",
                         [SPECIAL_GLYPH_ECSTATIC_SMILEY]         = ":-]",
                         [SPECIAL_GLYPH_HAPPY_SMILEY]            = ":-}",
                         [SPECIAL_GLYPH_SLIGHTLY_HAPPY_SMILEY]   = ":-)",
@@ -359,26 +358,34 @@ const char *special_glyph(SpecialGlyph code) {
 
                 /* UTF-8 */
                 [true] = {
+                        /* The following are multiple glyphs in both ASCII and in UNICODE */
                         [SPECIAL_GLYPH_TREE_VERTICAL]           = "\342\224\202 ",            /* │  */
                         [SPECIAL_GLYPH_TREE_BRANCH]             = "\342\224\234\342\224\200", /* ├─ */
                         [SPECIAL_GLYPH_TREE_RIGHT]              = "\342\224\224\342\224\200", /* └─ */
                         [SPECIAL_GLYPH_TREE_SPACE]              = "  ",                       /*    */
+
+                        /* Single glyphs in both cases */
                         [SPECIAL_GLYPH_TRIANGULAR_BULLET]       = "\342\200\243",             /* ‣ */
                         [SPECIAL_GLYPH_BLACK_CIRCLE]            = "\342\227\217",             /* ● */
                         [SPECIAL_GLYPH_BULLET]                  = "\342\200\242",             /* • */
-                        [SPECIAL_GLYPH_ARROW]                   = "\342\206\222",             /* → */
-                        [SPECIAL_GLYPH_MDASH]                   = "\342\200\223",             /* – */
-                        [SPECIAL_GLYPH_ELLIPSIS]                = "\342\200\246",             /* … */
-                        [SPECIAL_GLYPH_MU]                      = "\316\274",                 /* μ */
+                        [SPECIAL_GLYPH_MU]                      = "\316\274",                 /* μ (actually called: GREEK SMALL LETTER MU) */
                         [SPECIAL_GLYPH_CHECK_MARK]              = "\342\234\223",             /* ✓ */
-                        [SPECIAL_GLYPH_CROSS_MARK]              = "\342\234\227",             /* ✗ */
-                        [SPECIAL_GLYPH_ECSTATIC_SMILEY]         = "\360\237\230\207",         /* 😇 */
-                        [SPECIAL_GLYPH_HAPPY_SMILEY]            = "\360\237\230\200",         /* 😀 */
-                        [SPECIAL_GLYPH_SLIGHTLY_HAPPY_SMILEY]   = "\360\237\231\202",         /* 🙂 */
-                        [SPECIAL_GLYPH_NEUTRAL_SMILEY]          = "\360\237\230\220",         /* 😐 */
-                        [SPECIAL_GLYPH_SLIGHTLY_UNHAPPY_SMILEY] = "\360\237\231\201",         /* 🙁 */
-                        [SPECIAL_GLYPH_UNHAPPY_SMILEY]          = "\360\237\230\250",         /* 😨 */
-                        [SPECIAL_GLYPH_DEPRESSED_SMILEY]        = "\360\237\244\242",         /* 🤢 */
+                        [SPECIAL_GLYPH_CROSS_MARK]              = "\342\234\227",             /* ✗ (actually called: BALLOT X) */
+
+                        /* Single glyph in Unicode, two in ASCII */
+                        [SPECIAL_GLYPH_ARROW]                   = "\342\206\222",             /* → (actually called: RIGHTWARDS ARROW) */
+
+                        /* Single glyph in Unicode, three in ASCII */
+                        [SPECIAL_GLYPH_ELLIPSIS]                = "\342\200\246",             /* … (actually called: HORIZONTAL ELLIPSIS) */
+
+                        /* These smileys are a single glyph in Unicode, and three in ASCII */
+                        [SPECIAL_GLYPH_ECSTATIC_SMILEY]         = "\360\237\230\207",         /* 😇 (actually called: SMILING FACE WITH HALO) */
+                        [SPECIAL_GLYPH_HAPPY_SMILEY]            = "\360\237\230\200",         /* 😀 (actually called: GRINNING FACE) */
+                        [SPECIAL_GLYPH_SLIGHTLY_HAPPY_SMILEY]   = "\360\237\231\202",         /* 🙂 (actually called: SLIGHTLY SMILING FACE) */
+                        [SPECIAL_GLYPH_NEUTRAL_SMILEY]          = "\360\237\230\220",         /* 😐 (actually called: NEUTRAL FACE) */
+                        [SPECIAL_GLYPH_SLIGHTLY_UNHAPPY_SMILEY] = "\360\237\231\201",         /* 🙁 (actually called: SLIGHTLY FROWNING FACE) */
+                        [SPECIAL_GLYPH_UNHAPPY_SMILEY]          = "\360\237\230\250",         /* 😨 (actually called: FEARFUL FACE) */
+                        [SPECIAL_GLYPH_DEPRESSED_SMILEY]        = "\360\237\244\242",         /* 🤢 (actually called: NAUSEATED FACE) */
                 },
         };
 
index 78abbafd8f0b2d1f0b5657e8bf9c90564c1f8efc..1df8ac4cb0ce631a78a0ecea9da113976dd5dafa 100644 (file)
@@ -46,12 +46,11 @@ typedef enum {
         SPECIAL_GLYPH_TRIANGULAR_BULLET,
         SPECIAL_GLYPH_BLACK_CIRCLE,
         SPECIAL_GLYPH_BULLET,
-        SPECIAL_GLYPH_ARROW,
-        SPECIAL_GLYPH_MDASH,
-        SPECIAL_GLYPH_ELLIPSIS,
         SPECIAL_GLYPH_MU,
         SPECIAL_GLYPH_CHECK_MARK,
         SPECIAL_GLYPH_CROSS_MARK,
+        SPECIAL_GLYPH_ARROW,
+        SPECIAL_GLYPH_ELLIPSIS,
         _SPECIAL_GLYPH_FIRST_SMILEY,
         SPECIAL_GLYPH_ECSTATIC_SMILEY = _SPECIAL_GLYPH_FIRST_SMILEY,
         SPECIAL_GLYPH_HAPPY_SMILEY,
index 6ba880dbc4a5fa3c5828e742e855b15049c4113f..12bf77e7013a140930bffff0cdeabbb371fae98b 100644 (file)
 #include "string-util.h"
 #include "virt.h"
 
+static const char *const vm_table[_VIRTUALIZATION_MAX] = {
+        [VIRTUALIZATION_XEN]       = "XenVMMXenVMM",
+        [VIRTUALIZATION_KVM]       = "KVMKVMKVM",
+        [VIRTUALIZATION_QEMU]      = "TCGTCGTCGTCG",
+        /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
+        [VIRTUALIZATION_VMWARE]    = "VMwareVMware",
+        /* https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs */
+        [VIRTUALIZATION_MICROSOFT] = "Microsoft Hv",
+        /* https://wiki.freebsd.org/bhyve */
+        [VIRTUALIZATION_BHYVE]     = "bhyve bhyve ",
+        [VIRTUALIZATION_QNX]       = "QNXQVMBSQG",
+        /* https://projectacrn.org */
+        [VIRTUALIZATION_ACRN]      = "ACRNACRNACRN",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(vm, int);
+
 static int detect_vm_cpuid(void) {
 
         /* CPUID is an x86 specific interface. */
 #if defined(__i386__) || defined(__x86_64__)
 
-        static const struct {
-                const char *cpuid;
-                int id;
-        } cpuid_vendor_table[] = {
-                { "XenVMMXenVMM", VIRTUALIZATION_XEN       },
-                { "KVMKVMKVM",    VIRTUALIZATION_KVM       },
-                { "TCGTCGTCGTCG", VIRTUALIZATION_QEMU      },
-                /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
-                { "VMwareVMware", VIRTUALIZATION_VMWARE    },
-                /* https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs */
-                { "Microsoft Hv", VIRTUALIZATION_MICROSOFT },
-                /* https://wiki.freebsd.org/bhyve */
-                { "bhyve bhyve ", VIRTUALIZATION_BHYVE     },
-                { "QNXQVMBSQG",   VIRTUALIZATION_QNX       },
-                /* https://projectacrn.org */
-                { "ACRNACRNACRN", VIRTUALIZATION_ACRN      },
-        };
-
         uint32_t eax, ebx, ecx, edx;
         bool hypervisor;
 
@@ -59,7 +58,7 @@ static int detect_vm_cpuid(void) {
                         uint32_t sig32[3];
                         char text[13];
                 } sig = {};
-                unsigned j;
+                int v;
 
                 /* There is a hypervisor, see what it is */
                 __cpuid(0x40000000U, eax, ebx, ecx, edx);
@@ -70,11 +69,11 @@ static int detect_vm_cpuid(void) {
 
                 log_debug("Virtualization found, CPUID=%s", sig.text);
 
-                for (j = 0; j < ELEMENTSOF(cpuid_vendor_table); j ++)
-                        if (streq(sig.text, cpuid_vendor_table[j].cpuid))
-                                return cpuid_vendor_table[j].id;
+                v = vm_from_string(sig.text);
+                if (v < 0)
+                        return VIRTUALIZATION_VM_OTHER;
 
-                return VIRTUALIZATION_VM_OTHER;
+                return v;
         }
 #endif
         log_debug("No virtualization found in CPUID");
@@ -142,7 +141,7 @@ static int detect_vm_dmi(void) {
                 int id;
         } dmi_vendor_table[] = {
                 { "KVM",                 VIRTUALIZATION_KVM       },
-                { "QEMU",                VIRTUALIZATION_QEMU      },                
+                { "QEMU",                VIRTUALIZATION_QEMU      },
                 { "VMware",              VIRTUALIZATION_VMWARE    }, /* https://kb.vmware.com/s/article/1009458 */
                 { "VMW",                 VIRTUALIZATION_VMWARE    },
                 { "innotek GmbH",        VIRTUALIZATION_ORACLE    },
@@ -432,25 +431,23 @@ finish:
         return r;
 }
 
-int detect_container(void) {
-        static const struct {
-                const char *value;
-                int id;
-        } value_table[] = {
-                { "lxc",            VIRTUALIZATION_LXC            },
-                { "lxc-libvirt",    VIRTUALIZATION_LXC_LIBVIRT    },
-                { "systemd-nspawn", VIRTUALIZATION_SYSTEMD_NSPAWN },
-                { "docker",         VIRTUALIZATION_DOCKER         },
-                { "podman",         VIRTUALIZATION_PODMAN         },
-                { "rkt",            VIRTUALIZATION_RKT            },
-                { "wsl",            VIRTUALIZATION_WSL            },
-        };
+static const char *const container_table[_VIRTUALIZATION_MAX] = {
+        [VIRTUALIZATION_LXC]            = "lxc",
+        [VIRTUALIZATION_LXC_LIBVIRT]    = "lxc-libvirt",
+        [VIRTUALIZATION_SYSTEMD_NSPAWN] = "systemd-nspawn",
+        [VIRTUALIZATION_DOCKER]         = "docker",
+        [VIRTUALIZATION_PODMAN]         = "podman",
+        [VIRTUALIZATION_RKT]            = "rkt",
+        [VIRTUALIZATION_WSL]            = "wsl",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(container, int);
 
+int detect_container(void) {
         static thread_local int cached_found = _VIRTUALIZATION_INVALID;
         _cleanup_free_ char *m = NULL;
         _cleanup_free_ char *o = NULL;
         const char *e = NULL;
-        unsigned j;
         int r;
 
         if (cached_found >= 0)
@@ -532,13 +529,9 @@ int detect_container(void) {
         goto finish;
 
 translate_name:
-        for (j = 0; j < ELEMENTSOF(value_table); j++)
-                if (streq(e, value_table[j].value)) {
-                        r = value_table[j].id;
-                        goto finish;
-                }
-
-        r = VIRTUALIZATION_CONTAINER_OTHER;
+        r = container_from_string(e);
+        if (r < 0)
+                r = VIRTUALIZATION_CONTAINER_OTHER;
 
 finish:
         log_debug("Found container virtualization %s.", virtualization_to_string(r));
index c35d6ba4a5ba58dec09b811adaa4d27c684d17b4..a91db5df5f1f0adbf8bbc406d16a79f7c9128015 100644 (file)
@@ -124,6 +124,49 @@ int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char * const
         return 0;
 }
 
+int rtnl_set_link_alternative_names_by_ifname(sd_netlink **rtnl, const char *ifname, char * const *alternative_names) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
+        int r;
+
+        assert(rtnl);
+        assert(ifname);
+
+        if (strv_isempty(alternative_names))
+                return 0;
+
+        if (!*rtnl) {
+                r = sd_netlink_open(rtnl);
+                if (r < 0)
+                        return r;
+        }
+
+        r = sd_rtnl_message_new_link(*rtnl, &message, RTM_NEWLINKPROP, 0);
+        if (r < 0)
+                return r;
+
+        r = sd_netlink_message_append_string(message, IFLA_IFNAME, ifname);
+        if (r < 0)
+                return r;
+
+        r = sd_netlink_message_open_container(message, IFLA_PROP_LIST);
+        if (r < 0)
+                return r;
+
+        r = sd_netlink_message_append_strv(message, IFLA_ALT_IFNAME, alternative_names);
+        if (r < 0)
+                return r;
+
+        r = sd_netlink_message_close_container(message);
+        if (r < 0)
+                return r;
+
+        r = sd_netlink_call(*rtnl, message, 0, NULL);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
 int rtnl_resolve_link_alternative_name(sd_netlink **rtnl, const char *name, int *ret) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL;
         int r;
@@ -182,7 +225,7 @@ int rtnl_log_create_error(int r) {
 
 void rtattr_append_attribute_internal(struct rtattr *rta, unsigned short type, const void *data, size_t data_length) {
         size_t padding_length;
-        char *padding;
+        uint8_t *padding;
 
         assert(rta);
         assert(!data || data_length > 0);
@@ -202,7 +245,7 @@ void rtattr_append_attribute_internal(struct rtattr *rta, unsigned short type, c
                 padding = RTA_DATA(rta);
 
         /* make sure also the padding at the end of the message is initialized */
-        padding_length = (char *) rta + RTA_SPACE(data_length) - padding;
+        padding_length = (uint8_t *) rta + RTA_SPACE(data_length) - padding;
         memzero(padding, padding_length);
 }
 
index 1782786841115dde899f58c7471fba2d81542e0e..7b007a61c23ac04ec97f201374f2a71183c4c862 100644 (file)
@@ -50,6 +50,7 @@ static inline bool rtnl_message_type_is_qdisc(uint16_t type) {
 int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name);
 int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, uint32_t mtu);
 int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char * const *alternative_names);
+int rtnl_set_link_alternative_names_by_ifname(sd_netlink **rtnl, const char *ifname, char * const *alternative_names);
 int rtnl_resolve_link_alternative_name(sd_netlink **rtnl, const char *name, int *ret);
 
 int rtnl_log_parse_error(int r);
index 71d2bf0f8b7bb009d95b84cdffbbf8a5988b97ac..182a666746055ff6210e02ba1bcc63fe2f0c13cc 100644 (file)
@@ -512,8 +512,8 @@ int sd_rtnl_message_new_link(sd_netlink *rtnl, sd_netlink_message **ret,
 
         if (nlmsg_type == RTM_NEWLINK)
                 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
-        else if (nlmsg_type == RTM_NEWLINK)
-                (*ret)->hdr->nlmsg_flags |= NLM_F_EXCL | NLM_F_CREATE | NLM_F_APPEND;
+        else if (nlmsg_type == RTM_NEWLINKPROP)
+                (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL | NLM_F_APPEND;
 
         ifi = NLMSG_DATA((*ret)->hdr);
 
index 8b9ab8e9eb3320f9b270ea7067e21a179c63323e..3843ffbca9727c3884a57a494090b36bd28b0c6d 100644 (file)
@@ -239,12 +239,11 @@ if conf.get('ENABLE_NETWORKD') == 1
       test_tables_h],
      [libnetworkd_core,
       libudev_static,
-      libudev_core,
       libsystemd_network,
       libshared],
      [threads],
      '', '', [],
-     [network_include_dir] + libudev_core_includes],
+     [network_include_dir]],
 
     [['src/network/generator/test-network-generator.c',
       'src/network/generator/network-generator.c',
index 66d83e76bfae4ffd3c590999c01cc051d3b4445f..70377ad6bb5b0bd18b30397da46e161222f09cd7 100644 (file)
@@ -377,6 +377,23 @@ static int link_set_dhcp_routes(Link *link) {
                         return log_link_error_errno(link, r, "Could not set router: %m");
         }
 
+        Route *rt;
+        LIST_FOREACH(routes, rt, link->network->static_routes) {
+                if (!rt->gateway_from_dhcp)
+                        continue;
+
+                if (rt->family != AF_INET)
+                        continue;
+
+                rt->gw.in = router[0];
+
+                r = route_configure(rt, link, dhcp4_route_handler);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not set gateway: %m");
+                if (r > 0)
+                        link->dhcp4_messages++;
+        }
+
         return link_set_dns_routes(link, &address);
 }
 
@@ -480,6 +497,20 @@ static int dhcp_remove_router(Link *link, sd_dhcp_lease *lease, const struct in_
         if (remove_all || !set_contains(link->dhcp_routes, route))
                 (void) route_remove(route, link, NULL);
 
+        Route *rt;
+        LIST_FOREACH(routes, rt, link->network->static_routes) {
+                if (!rt->gateway_from_dhcp)
+                        continue;
+
+                if (rt->family != AF_INET)
+                        continue;
+
+                if (!remove_all && in4_addr_equal(router, &rt->gw.in))
+                        continue;
+
+                (void) route_remove(rt, link, NULL);
+        }
+
         return 0;
 }
 
index 23d0ee675b007ba9a4c9496bfb337e783c9293e9..f2027057c44f39782731d290cfee6c63e7588486 100644 (file)
@@ -1039,6 +1039,8 @@ int link_request_set_routes(Link *link) {
         /* First add the routes that enable us to talk to gateways, then add in the others that need a gateway. */
         for (phase = 0; phase < _PHASE_MAX; phase++)
                 LIST_FOREACH(routes, rt, link->network->static_routes) {
+                        if (rt->gateway_from_dhcp)
+                                continue;
 
                         if ((in_addr_is_null(rt->family, &rt->gw) && ordered_set_isempty(rt->multipath_routes)) != (phase == PHASE_NON_GATEWAY))
                                 continue;
index f4e4162cf1213e19e39126a0f9fc9699b5516d0d..380f5c1c61f14613e113284964e9f29c931b092e 100644 (file)
@@ -695,8 +695,8 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message,
                                        strnull(addr_str), strnull(lladdr_str));
                         (void) neighbor_free(neighbor);
                 } else
-                        log_link_info(link, "Kernel removed a neighbor we don't remember: %s->%s, ignoring.",
-                                      strnull(addr_str), strnull(lladdr_str));
+                        log_link_debug(link, "Kernel removed a neighbor we don't remember: %s->%s, ignoring.",
+                                       strnull(addr_str), strnull(lladdr_str));
 
                 break;
 
@@ -855,9 +855,9 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
                                        valid_str ? "for " : "forever", strempty(valid_str));
                         (void) address_drop(address);
                 } else
-                        log_link_info(link, "Kernel removed an address we don't remember: %s/%u (valid %s%s), ignoring.",
-                                      strnull(buf), prefixlen,
-                                      valid_str ? "for " : "forever", strempty(valid_str));
+                        log_link_debug(link, "Kernel removed an address we don't remember: %s/%u (valid %s%s), ignoring.",
+                                       strnull(buf), prefixlen,
+                                       valid_str ? "for " : "forever", strempty(valid_str));
 
                 break;
 
index d1db9e4931c17e9d84cd837f2c01bf432d312544..fb3d6f2a841ace03b792adfbf004c3042ae658f5 100644 (file)
@@ -169,6 +169,26 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
         if (r > 0)
                 link->ndisc_messages++;
 
+        Route *route_gw;
+        LIST_FOREACH(routes, route_gw, link->network->static_routes) {
+                if (!route_gw->gateway_from_dhcp)
+                        continue;
+
+                if (route_gw->family != AF_INET6)
+                        continue;
+
+                route_gw->gw = gateway;
+
+                r = route_configure(route_gw, link, ndisc_netlink_route_message_handler);
+                if (r < 0) {
+                        log_link_error_errno(link, r, "Could not set gateway: %m");
+                        link_enter_failed(link);
+                        return r;
+                }
+                if (r > 0)
+                        link->ndisc_messages++;
+        }
+
         return 0;
 }
 
index ecc8d219b7d1d59da62a3a31b19b94de35ddd23c..4e90fdef18535dd3e4cf66680493cf876669e88d 100644 (file)
@@ -998,10 +998,19 @@ int config_parse_gateway(
                 /* we are not in an Route section, so treat
                  * this as the special '0' section */
                 r = route_new_static(network, NULL, 0, &n);
-        } else
+                if (r < 0)
+                        return r;
+        } else {
                 r = route_new_static(network, filename, section_line, &n);
-        if (r < 0)
-                return r;
+                if (r < 0)
+                        return r;
+
+                if (streq(rvalue, "dhcp")) {
+                        n->gateway_from_dhcp = true;
+                        TAKE_PTR(n);
+                        return 0;
+                }
+        }
 
         if (n->family == AF_UNSPEC)
                 r = in_addr_from_string_auto(rvalue, &n->family, &n->gw);
index 91bba368ee21f73e14c5108a889f19667ef3dc64..067c65f2f78217eb387d953526525ee2b8785e35 100644 (file)
@@ -48,6 +48,7 @@ struct Route {
         unsigned char pref;
         unsigned flags;
         int gateway_onlink;
+        bool gateway_from_dhcp;
 
         union in_addr_union gw;
         union in_addr_union dst;
index f423f625905ef2fa7bf082d9ffee3ce84bd80e37..6afc31d824b345a3deecd9456a6caf677c9be7dc 100644 (file)
@@ -989,6 +989,19 @@ int mount_custom(
         return 0;
 }
 
+bool has_custom_root_mount(const CustomMount *mounts, size_t n) {
+        size_t i;
+
+        for (i = 0; i < n; i++) {
+                const CustomMount *m = mounts + i;
+
+                if (path_equal(m->destination, "/"))
+                        return true;
+        }
+
+        return false;
+}
+
 static int setup_volatile_state(const char *directory, uid_t uid_shift, const char *selinux_apifs_context) {
 
         _cleanup_free_ char *buf = NULL;
index aabc9e29bef5161e66ca02b03dbae897d3726602..680ff350e5d33a12ccc8480247d8665be79654c7 100644 (file)
@@ -55,6 +55,7 @@ int mount_all(const char *dest, MountSettingsMask mount_settings, uid_t uid_shif
 int mount_sysfs(const char *dest, MountSettingsMask mount_settings);
 
 int mount_custom(const char *dest, CustomMount *mounts, size_t n, uid_t uid_shift, const char *selinux_apifs_context, MountSettingsMask mount_settings);
+bool has_custom_root_mount(const CustomMount *mounts, size_t n);
 
 int setup_volatile_mode(const char *directory, VolatileMode mode, uid_t uid_shift, const char *selinux_apifs_context);
 
index e91a9d36bf334302db28ae72d241cfea5c31c614..9c9cf4812e8f2cb8a0fea709dcefd443c89c5f7e 100644 (file)
@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
+#include <net/if.h>
+#include <linux/if.h>
 #include <linux/veth.h>
 #include <sys/file.h>
 
@@ -99,10 +101,34 @@ static int generate_mac(
         return 0;
 }
 
+static int set_alternative_ifname(sd_netlink *rtnl, const char *ifname, const char *altifname) {
+        int r;
+
+        assert(rtnl);
+        assert(ifname);
+
+        if (!altifname)
+                return 0;
+
+        if (strlen(altifname) >= ALTIFNAMSIZ)
+                return log_warning_errno(SYNTHETIC_ERRNO(ERANGE),
+                                         "Alternative interface name '%s' for '%s' is too long, ignoring",
+                                         altifname, ifname);
+
+        r = rtnl_set_link_alternative_names_by_ifname(&rtnl, ifname, STRV_MAKE(altifname));
+        if (r < 0)
+                return log_warning_errno(r,
+                                         "Failed to set alternative interface name '%s' to '%s', ignoring: %m",
+                                         altifname, ifname);
+
+        return 0;
+}
+
 static int add_veth(
                 sd_netlink *rtnl,
                 pid_t pid,
                 const char *ifname_host,
+                const char *altifname_host,
                 const struct ether_addr *mac_host,
                 const char *ifname_container,
                 const struct ether_addr *mac_container) {
@@ -168,6 +194,8 @@ static int add_veth(
         if (r < 0)
                 return log_error_errno(r, "Failed to add new veth interfaces (%s:%s): %m", ifname_host, ifname_container);
 
+        (void) set_alternative_ifname(rtnl, ifname_host, altifname_host);
+
         return 0;
 }
 
@@ -181,13 +209,13 @@ static char urlsafe_base64char(int x) {
         return table[x & 63];
 }
 
-static void shorten_ifname(char *ifname) {
+static int shorten_ifname(char *ifname) {
         char new_ifname[IFNAMSIZ];
 
         assert(ifname);
 
         if (strlen(ifname) < IFNAMSIZ) /* Name is short enough */
-                return;
+                return 0;
 
         if (naming_scheme_has(NAMING_NSPAWN_LONG_HASH)) {
                 uint64_t h;
@@ -211,6 +239,7 @@ static void shorten_ifname(char *ifname) {
         log_warning("Network interface name '%s' has been changed to '%s' to fit length constraints.", ifname, new_ifname);
 
         strcpy(ifname, new_ifname);
+        return 1;
 }
 
 int setup_veth(const char *machine_name,
@@ -221,7 +250,7 @@ int setup_veth(const char *machine_name,
         _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         struct ether_addr mac_host, mac_container;
         unsigned u;
-        char *n;
+        char *n, *a = NULL;
         int r;
 
         assert(machine_name);
@@ -231,7 +260,9 @@ int setup_veth(const char *machine_name,
         /* Use two different interface name prefixes depending whether
          * we are in bridge mode or not. */
         n = strjoina(bridge ? "vb-" : "ve-", machine_name);
-        shorten_ifname(n);
+        r = shorten_ifname(n);
+        if (r > 0)
+                a = strjoina(bridge ? "vb-" : "ve-", machine_name);
 
         r = generate_mac(machine_name, &mac_container, CONTAINER_HASH_KEY, 0);
         if (r < 0)
@@ -245,7 +276,7 @@ int setup_veth(const char *machine_name,
         if (r < 0)
                 return log_error_errno(r, "Failed to connect to netlink: %m");
 
-        r = add_veth(rtnl, pid, n, &mac_host, "host0", &mac_container);
+        r = add_veth(rtnl, pid, n, a, &mac_host, "host0", &mac_container);
         if (r < 0)
                 return r;
 
@@ -288,7 +319,7 @@ int setup_veth_extra(
                 if (r < 0)
                         return log_error_errno(r, "Failed to generate predictable MAC address for container side of extra veth link: %m");
 
-                r = add_veth(rtnl, pid, *a, &mac_host, *b, &mac_container);
+                r = add_veth(rtnl, pid, *a, NULL, &mac_host, *b, &mac_container);
                 if (r < 0)
                         return r;
 
@@ -536,7 +567,7 @@ int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces) {
 
         STRV_FOREACH(i, ifaces) {
                 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
-                _cleanup_free_ char *n = NULL;
+                _cleanup_free_ char *n = NULL, *a = NULL;
                 struct ether_addr mac;
                 int ifi;
 
@@ -560,7 +591,12 @@ int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces) {
                 if (!n)
                         return log_oom();
 
-                shorten_ifname(n);
+                r = shorten_ifname(n);
+                if (r > 0) {
+                        a = strjoin("mv-", *i);
+                        if (!a)
+                                return log_oom();
+                }
 
                 r = sd_netlink_message_append_string(m, IFLA_IFNAME, n);
                 if (r < 0)
@@ -597,6 +633,8 @@ int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces) {
                 r = sd_netlink_call(rtnl, m, 0, NULL);
                 if (r < 0)
                         return log_error_errno(r, "Failed to add new macvlan interfaces: %m");
+
+                (void) set_alternative_ifname(rtnl, n, a);
         }
 
         return 0;
@@ -616,7 +654,7 @@ int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces) {
 
         STRV_FOREACH(i, ifaces) {
                 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
-                _cleanup_free_ char *n = NULL;
+                _cleanup_free_ char *n = NULL, *a = NULL;
                 int ifi;
 
                 ifi = parse_interface(*i);
@@ -635,7 +673,12 @@ int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces) {
                 if (!n)
                         return log_oom();
 
-                shorten_ifname(n);
+                r = shorten_ifname(n);
+                if (r > 0) {
+                        a = strjoin("iv-", *i);
+                        if (!a)
+                                return log_oom();
+                }
 
                 r = sd_netlink_message_append_string(m, IFLA_IFNAME, n);
                 if (r < 0)
@@ -668,6 +711,8 @@ int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces) {
                 r = sd_netlink_call(rtnl, m, 0, NULL);
                 if (r < 0)
                         return log_error_errno(r, "Failed to add new ipvlan interfaces: %m");
+
+                (void) set_alternative_ifname(rtnl, n, a);
         }
 
         return 0;
index 32294ed00293e31e1daf33c203d1476369c52532..791bdd35321a64f171603ed0f3d516ad213ef7b7 100644 (file)
@@ -1541,6 +1541,9 @@ static int verify_arguments(void) {
         if (arg_volatile_mode != VOLATILE_NO) /* Make sure all file systems contained in the image are mounted read-only if we are in volatile mode */
                 arg_read_only = true;
 
+        if (has_custom_root_mount(arg_custom_mounts, arg_n_custom_mounts))
+                arg_read_only = true;
+
         if (arg_keep_unit && arg_register && cg_pid_get_owner_uid(0, NULL) >= 0)
                 /* Save the user from accidentally registering either user-$SESSION.scope or user@.service.
                  * The latter is not technically a user session, but we don't need to labour the point. */
@@ -3438,7 +3441,8 @@ static int outer_child(
         if (r < 0)
                 return r;
 
-        if (arg_read_only && arg_volatile_mode == VOLATILE_NO) {
+        if (arg_read_only && arg_volatile_mode == VOLATILE_NO &&
+                !has_custom_root_mount(arg_custom_mounts, arg_n_custom_mounts)) {
                 r = bind_remount_recursive(directory, MS_RDONLY, MS_RDONLY, NULL);
                 if (r < 0)
                         return log_error_errno(r, "Failed to make tree read-only: %m");
index fac98ad0eadf09c9de80e9ed3c84ccaa27dd49e5..3fcd7630db6bd429c2fd154168e7d728b84db61f 100644 (file)
@@ -218,7 +218,7 @@ int pkcs11_token_login(
                         r = asprintf(&text,
                                      "Please enter correct PIN for security token '%s' in order to unlock %s (final try):",
                                      token_label, friendly_name);
-                if (FLAGS_SET(token_info->flags, CKF_USER_PIN_COUNT_LOW))
+                else if (FLAGS_SET(token_info->flags, CKF_USER_PIN_COUNT_LOW))
                         r = asprintf(&text,
                                      "PIN has been entered incorrectly previously, please enter correct PIN for security token '%s' in order to unlock %s:",
                                      token_label, friendly_name);
index 28d90be8964d1b19da6ed29f1bd8c6fc226da777..f49cc6371ef0a21bd7278b520edbbdde99512761 100644 (file)
@@ -81,7 +81,6 @@ static void dump_special_glyphs(void) {
         dump_glyph(SPECIAL_GLYPH_BLACK_CIRCLE);
         dump_glyph(SPECIAL_GLYPH_BULLET);
         dump_glyph(SPECIAL_GLYPH_ARROW);
-        dump_glyph(SPECIAL_GLYPH_MDASH);
         dump_glyph(SPECIAL_GLYPH_ELLIPSIS);
         dump_glyph(SPECIAL_GLYPH_MU);
         dump_glyph(SPECIAL_GLYPH_CHECK_MARK);
index 6168b332d3b23f8801dbc2db4952d72329c5716e..b9b350d1ef7a4f8064a7a7bd1e6b796d4bfaff7a 100644 (file)
@@ -1654,7 +1654,7 @@ static int udev_rule_apply_token_to_event(
                 if (mode == MODE_INVALID)
                         return token->op == OP_MATCH;
 
-                match = (((statbuf.st_mode ^ mode) & 07777) == 0);
+                match = (statbuf.st_mode & mode) > 0;
                 return token->op == (match ? OP_MATCH : OP_NOMATCH);
         }
         case TK_M_PROGRAM: {
diff --git a/test/test-network/conf/dhcp-client-gateway-ipv4.network b/test/test-network/conf/dhcp-client-gateway-ipv4.network
new file mode 100644 (file)
index 0000000..1b8a375
--- /dev/null
@@ -0,0 +1,10 @@
+[Match]
+Name=veth99
+
+[Network]
+DHCP=ipv4
+IPv6AcceptRA=no
+
+[Route]
+Gateway=dhcp
+Destination=10.0.0.0/8
diff --git a/test/test-network/conf/dhcp-client-gateway-ipv6.network b/test/test-network/conf/dhcp-client-gateway-ipv6.network
new file mode 100644 (file)
index 0000000..058cb33
--- /dev/null
@@ -0,0 +1,9 @@
+[Match]
+Name=veth99
+
+[Network]
+DHCP=ipv6
+
+[Route]
+Gateway=dhcp
+Destination=2001:1234:5:9fff:ff:ff:ff:ff/128
index 90b1a8b14072cbaf8f06d51af0c1abae9b0d5b7a..d9b5df18dfe66231fc64f3fb405bfdce71e2d09f 100755 (executable)
@@ -2659,6 +2659,8 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         '25-vrf.network',
         'dhcp-client-anonymize.network',
         'dhcp-client-decline.network',
+        'dhcp-client-gateway-ipv4.network',
+        'dhcp-client-gateway-ipv6.network',
         'dhcp-client-gateway-onlink-implicit.network',
         'dhcp-client-ipv4-dhcp-settings.network',
         'dhcp-client-ipv4-only-ipv6-disabled.network',
@@ -3145,6 +3147,30 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         print(output)
         self.assertEqual(output, '')
 
+    def test_dhcp_client_gateway_ipv4(self):
+        copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
+                                        'dhcp-client-gateway-ipv4.network')
+        start_networkd()
+        self.wait_online(['veth-peer:carrier'])
+        start_dnsmasq()
+        self.wait_online(['veth99:routable', 'veth-peer:routable'])
+
+        output = check_output('ip route list dev veth99 10.0.0.0/8')
+        print(output)
+        self.assertRegex(output, '10.0.0.0/8 via 192.168.5.1 proto static')
+
+    def test_dhcp_client_gateway_ipv6(self):
+        copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
+                                        'dhcp-client-gateway-ipv6.network')
+        start_networkd()
+        self.wait_online(['veth-peer:carrier'])
+        start_dnsmasq()
+        self.wait_online(['veth99:routable', 'veth-peer:routable'])
+
+        output = check_output('ip -6 route list dev veth99 2001:1234:5:9fff:ff:ff:ff:ff')
+        print(output)
+        self.assertRegex(output, 'via fe80::1034:56ff:fe78:9abd')
+
     def test_dhcp_client_gateway_onlink_implicit(self):
         copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
                                         'dhcp-client-gateway-onlink-implicit.network')
index c809011fc5ea6e4dc457d5f31f708830c20bc913..4ad64d12f255f7a6fc4cb3413cc48dbadab656a6 100644 (file)
@@ -35,6 +35,7 @@ units = [
         ['local-fs.target',                     ''],
         ['machine.slice',                       'ENABLE_MACHINED'],
         ['machines.target',                     'ENABLE_MACHINED'],
+        ['modprobe@.service',                   ''],
         ['multi-user.target',                   '',
          'runlevel2.target runlevel3.target runlevel4.target'],
         ['network-online.target',               ''],
diff --git a/units/modprobe@.service b/units/modprobe@.service
new file mode 100644 (file)
index 0000000..4c5bd63
--- /dev/null
@@ -0,0 +1,16 @@
+#  SPDX-License-Identifier: LGPL-2.1+
+#
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=Load kernel module %i
+Documentation=man:modprobe(8)
+
+[Service]
+Type=oneshot
+ExecStart=-/sbin/modprobe -abq %I
index ccbe6315860d0107b40f8f511587fa03e3dbc12b..23aa828591c434939679b796166237fde60dcf2e 100644 (file)
@@ -12,8 +12,8 @@ Description=Login Service
 Documentation=man:systemd-logind.service(8) man:logind.conf(5)
 Documentation=https://www.freedesktop.org/wiki/Software/systemd/logind
 Documentation=https://www.freedesktop.org/wiki/Software/systemd/multiseat
-Wants=user.slice
-After=nss-user-lookup.target user.slice
+Wants=user.slice modprobe@drm.service
+After=nss-user-lookup.target user.slice modprobe@drm.service
 
 # Ask for the dbus socket.
 Wants=dbus.socket
@@ -29,7 +29,6 @@ DeviceAllow=char-input rw
 DeviceAllow=char-tty rw
 DeviceAllow=char-vcs rw
 # Make sure the DeviceAllow= lines above can work correctly when referenceing char-drm
-ExecStartPre=-/sbin/modprobe -abq drm
 ExecStart=@rootlibexecdir@/systemd-logind
 FileDescriptorStoreMax=512
 IPAddressDeny=any
index 669fea3c12ca0f0b01cffb82e2d5c9e008e93828..5367ee44105b3bf7dddd21e2773f5473bdee7a64 100644 (file)
 [Unit]
 Description=Container %i
 Documentation=man:systemd-nspawn(1)
+Wants=modprobe@tun.service modprobe@loop.service modprobe@dm-mod.service
 PartOf=machines.target
 Before=machines.target
-After=network.target systemd-resolved.service
+After=network.target systemd-resolved.service modprobe@tun.service modprobe@loop.service modprobe@dm-mod.service
 RequiresMountsFor=/var/lib/machines
 
 [Service]
 # Make sure the DeviceAllow= lines below can properly resolve the 'block-loop' expression (and others)
-ExecStartPre=-/sbin/modprobe -abq tun loop dm-mod
 ExecStart=@bindir@/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --network-veth -U --settings=override --machine=%i
 KillMode=mixed
 Type=notify