</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
<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>
[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] = ":-)",
/* 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) */
},
};
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,
#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;
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);
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");
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 },
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)
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));
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;
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);
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);
}
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);
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);
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',
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);
}
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;
}
/* 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;
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;
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;
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;
}
/* 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);
unsigned char pref;
unsigned flags;
int gateway_onlink;
+ bool gateway_from_dhcp;
union in_addr_union gw;
union in_addr_union dst;
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;
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);
/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <net/if.h>
+#include <linux/if.h>
#include <linux/veth.h>
#include <sys/file.h>
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) {
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;
}
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;
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,
_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);
/* 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)
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;
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;
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;
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)
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;
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);
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)
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;
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. */
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");
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);
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);
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: {
--- /dev/null
+[Match]
+Name=veth99
+
+[Network]
+DHCP=ipv4
+IPv6AcceptRA=no
+
+[Route]
+Gateway=dhcp
+Destination=10.0.0.0/8
--- /dev/null
+[Match]
+Name=veth99
+
+[Network]
+DHCP=ipv6
+
+[Route]
+Gateway=dhcp
+Destination=2001:1234:5:9fff:ff:ff:ff:ff/128
'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',
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')
['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', ''],
--- /dev/null
+# 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
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
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
[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