mirror of
https://github.com/systemd/systemd
synced 2024-09-06 16:56:43 +00:00
nspawn: container network interface naming
systemd-nspawn now optionally supports colon-separated pair of host interface name and container interface name for --network-macvlan, --network-ipvlan and --network-interface options. Also supported in .nspawn configuration files (i.e Interface=, MACVLAN=, IPVLAN= parameters). man page changed for ntwk interface naming
This commit is contained in:
parent
3af48a86d9
commit
2f091b1b49
|
@ -852,11 +852,13 @@
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--network-interface=</option></term>
|
<term><option>--network-interface=</option></term>
|
||||||
|
|
||||||
<listitem><para>Assign the specified network interface to the container. This will remove the
|
<listitem><para>Assign the specified network interface to the container. Either takes a single
|
||||||
specified interface from the calling namespace and place it in the container. When the container
|
interface name, referencing the name on the host, or a colon-separated pair of interfaces, in which
|
||||||
terminates, it is moved back to the calling namespace. Note that
|
case the first one references the name on the host, and the second one the name in the container.
|
||||||
<option>--network-interface=</option> implies <option>--private-network</option>. This option may be
|
When the container terminates, the interface is moved back to the calling namespace and renamed to
|
||||||
used more than once to add multiple network interfaces to the container.</para>
|
its original name. Note that <option>--network-interface=</option> implies
|
||||||
|
<option>--private-network</option>. This option may be used more than once to add multiple network
|
||||||
|
interfaces to the container.</para>
|
||||||
|
|
||||||
<para>Note that any network interface specified this way must already exist at the time the container
|
<para>Note that any network interface specified this way must already exist at the time the container
|
||||||
is started. If the container shall be started automatically at boot via a
|
is started. If the container shall be started automatically at boot via a
|
||||||
|
@ -880,9 +882,12 @@ After=sys-subsystem-net-devices-ens1.device</programlisting>
|
||||||
<term><option>--network-macvlan=</option></term>
|
<term><option>--network-macvlan=</option></term>
|
||||||
|
|
||||||
<listitem><para>Create a <literal>macvlan</literal> interface of the specified Ethernet network
|
<listitem><para>Create a <literal>macvlan</literal> interface of the specified Ethernet network
|
||||||
interface and add it to the container. A <literal>macvlan</literal> interface is a virtual interface
|
interface and add it to the container. Either takes a single interface name, referencing the name
|
||||||
that adds a second MAC address to an existing physical Ethernet link. The interface in the container
|
on the host, or a colon-separated pair of interfaces, in which case the first one references the name
|
||||||
will be named after the interface on the host, prefixed with <literal>mv-</literal>. Note that
|
on the host, and the second one the name in the container. A <literal>macvlan</literal> interface is
|
||||||
|
a virtual interface that adds a second MAC address to an existing physical Ethernet link. If the
|
||||||
|
container interface name is not defined, the interface in the container will be named after the
|
||||||
|
interface on the host, prefixed with <literal>mv-</literal>. Note that
|
||||||
<option>--network-macvlan=</option> implies <option>--private-network</option>. This option may be
|
<option>--network-macvlan=</option> implies <option>--private-network</option>. This option may be
|
||||||
used more than once to add multiple network interfaces to the container.</para>
|
used more than once to add multiple network interfaces to the container.</para>
|
||||||
|
|
||||||
|
@ -895,9 +900,13 @@ After=sys-subsystem-net-devices-ens1.device</programlisting>
|
||||||
<term><option>--network-ipvlan=</option></term>
|
<term><option>--network-ipvlan=</option></term>
|
||||||
|
|
||||||
<listitem><para>Create an <literal>ipvlan</literal> interface of the specified Ethernet network
|
<listitem><para>Create an <literal>ipvlan</literal> interface of the specified Ethernet network
|
||||||
interface and add it to the container. An <literal>ipvlan</literal> interface is a virtual interface,
|
interface and add it to the container. Either takes a single interface name, referencing the name on
|
||||||
|
the host, or a colon-separated pair of interfaces, in which case the first one references the name
|
||||||
|
on the host, and the second one the name in the container. An <literal>ipvlan</literal> interface is
|
||||||
|
a virtual interface,
|
||||||
similar to a <literal>macvlan</literal> interface, which uses the same MAC address as the underlying
|
similar to a <literal>macvlan</literal> interface, which uses the same MAC address as the underlying
|
||||||
interface. The interface in the container will be named after the interface on the host, prefixed
|
interface. If the container interface name is not defined, the interface in the container will be
|
||||||
|
named after the interface on the host, prefixed
|
||||||
with <literal>iv-</literal>. Note that <option>--network-ipvlan=</option> implies
|
with <literal>iv-</literal>. Note that <option>--network-ipvlan=</option> implies
|
||||||
<option>--private-network</option>. This option may be used more than once to add multiple network
|
<option>--private-network</option>. This option may be used more than once to add multiple network
|
||||||
interfaces to the container.</para>
|
interfaces to the container.</para>
|
||||||
|
|
|
@ -531,8 +531,11 @@
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>Interface=</varname></term>
|
<term><varname>Interface=</varname></term>
|
||||||
|
|
||||||
<listitem><para>Takes a space-separated list of interfaces to
|
<listitem><para>Takes a space-separated list of interfaces to add to the container.
|
||||||
add to the container. This option corresponds to the
|
The interface object is defined either by a single interface name, referencing the name on the host,
|
||||||
|
or a colon-separated pair of interfaces, in which case the first one references the name on the host,
|
||||||
|
and the second one the name in the container.
|
||||||
|
This option corresponds to the
|
||||||
<option>--network-interface=</option> command line switch and
|
<option>--network-interface=</option> command line switch and
|
||||||
implies <varname>Private=yes</varname>. This option is
|
implies <varname>Private=yes</varname>. This option is
|
||||||
privileged (see above).</para></listitem>
|
privileged (see above).</para></listitem>
|
||||||
|
@ -544,7 +547,9 @@
|
||||||
|
|
||||||
<listitem><para>Takes a space-separated list of interfaces to
|
<listitem><para>Takes a space-separated list of interfaces to
|
||||||
add MACLVAN or IPVLAN interfaces to, which are then added to
|
add MACLVAN or IPVLAN interfaces to, which are then added to
|
||||||
the container. These options correspond to the
|
the container. The interface object is defined either by a single interface name, referencing the name
|
||||||
|
on the host, or a colon-separated pair of interfaces, in which case the first one references the name
|
||||||
|
on the host, and the second one the name in the container. These options correspond to the
|
||||||
<option>--network-macvlan=</option> and
|
<option>--network-macvlan=</option> and
|
||||||
<option>--network-ipvlan=</option> command line switches and
|
<option>--network-ipvlan=</option> command line switches and
|
||||||
imply <varname>Private=yes</varname>. These options are
|
imply <varname>Private=yes</varname>. These options are
|
||||||
|
|
|
@ -72,9 +72,9 @@ Files.PrivateUsersChown, config_parse_userns_chown, 0,
|
||||||
Files.PrivateUsersOwnership, config_parse_userns_ownership, 0, offsetof(Settings, userns_ownership)
|
Files.PrivateUsersOwnership, config_parse_userns_ownership, 0, offsetof(Settings, userns_ownership)
|
||||||
Files.BindUser, config_parse_bind_user, 0, offsetof(Settings, bind_user)
|
Files.BindUser, config_parse_bind_user, 0, offsetof(Settings, bind_user)
|
||||||
Network.Private, config_parse_tristate, 0, offsetof(Settings, private_network)
|
Network.Private, config_parse_tristate, 0, offsetof(Settings, private_network)
|
||||||
Network.Interface, config_parse_strv, 0, offsetof(Settings, network_interfaces)
|
Network.Interface, config_parse_network_iface_pair, 0, offsetof(Settings, network_interfaces)
|
||||||
Network.MACVLAN, config_parse_strv, 0, offsetof(Settings, network_macvlan)
|
Network.MACVLAN, config_parse_macvlan_iface_pair, 0, offsetof(Settings, network_macvlan)
|
||||||
Network.IPVLAN, config_parse_strv, 0, offsetof(Settings, network_ipvlan)
|
Network.IPVLAN, config_parse_ipvlan_iface_pair, 0, offsetof(Settings, network_ipvlan)
|
||||||
Network.VirtualEthernet, config_parse_tristate, 0, offsetof(Settings, network_veth)
|
Network.VirtualEthernet, config_parse_tristate, 0, offsetof(Settings, network_veth)
|
||||||
Network.VirtualEthernetExtra, config_parse_veth_extra, 0, 0
|
Network.VirtualEthernetExtra, config_parse_veth_extra, 0, 0
|
||||||
Network.Bridge, config_parse_ifname, 0, offsetof(Settings, network_bridge)
|
Network.Bridge, config_parse_ifname, 0, offsetof(Settings, network_bridge)
|
||||||
|
|
|
@ -463,7 +463,7 @@ int remove_bridge(const char *bridge_name) {
|
||||||
return remove_one_link(rtnl, bridge_name);
|
return remove_one_link(rtnl, bridge_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
int test_network_interface_initialized(const char *name) {
|
static int test_network_interface_initialized(const char *name) {
|
||||||
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
|
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -491,18 +491,28 @@ int test_network_interface_initialized(const char *name) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int move_network_interfaces(int netns_fd, char **ifaces) {
|
int test_network_interfaces_initialized(char **iface_pairs) {
|
||||||
|
int r;
|
||||||
|
STRV_FOREACH_PAIR(a, b, iface_pairs) {
|
||||||
|
r = test_network_interface_initialized(*a);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int move_network_interfaces(int netns_fd, char **iface_pairs) {
|
||||||
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (strv_isempty(ifaces))
|
if (strv_isempty(iface_pairs))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = sd_netlink_open(&rtnl);
|
r = sd_netlink_open(&rtnl);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to connect to netlink: %m");
|
return log_error_errno(r, "Failed to connect to netlink: %m");
|
||||||
|
|
||||||
STRV_FOREACH(i, ifaces) {
|
STRV_FOREACH_PAIR(i, b, iface_pairs) {
|
||||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||||
int ifi;
|
int ifi;
|
||||||
|
|
||||||
|
@ -518,6 +528,12 @@ int move_network_interfaces(int netns_fd, char **ifaces) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to append namespace fd to netlink message: %m");
|
return log_error_errno(r, "Failed to append namespace fd to netlink message: %m");
|
||||||
|
|
||||||
|
if (!streq(*b, *i)) {
|
||||||
|
r = sd_netlink_message_append_string(m, IFLA_IFNAME, *b);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to add netlink interface name: %m");
|
||||||
|
}
|
||||||
|
|
||||||
r = sd_netlink_call(rtnl, m, 0, NULL);
|
r = sd_netlink_call(rtnl, m, 0, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to move interface %s to namespace: %m", *i);
|
return log_error_errno(r, "Failed to move interface %s to namespace: %m", *i);
|
||||||
|
@ -526,23 +542,23 @@ int move_network_interfaces(int netns_fd, char **ifaces) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces) {
|
int setup_macvlan(const char *machine_name, pid_t pid, char **iface_pairs) {
|
||||||
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
||||||
unsigned idx = 0;
|
unsigned idx = 0;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (strv_isempty(ifaces))
|
if (strv_isempty(iface_pairs))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = sd_netlink_open(&rtnl);
|
r = sd_netlink_open(&rtnl);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to connect to netlink: %m");
|
return log_error_errno(r, "Failed to connect to netlink: %m");
|
||||||
|
|
||||||
STRV_FOREACH(i, ifaces) {
|
STRV_FOREACH_PAIR(i, b, iface_pairs) {
|
||||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||||
_cleanup_free_ char *n = NULL, *a = NULL;
|
_cleanup_free_ char *n = NULL;
|
||||||
|
int shortened, ifi;
|
||||||
struct ether_addr mac;
|
struct ether_addr mac;
|
||||||
int ifi;
|
|
||||||
|
|
||||||
ifi = rtnl_resolve_interface_or_warn(&rtnl, *i);
|
ifi = rtnl_resolve_interface_or_warn(&rtnl, *i);
|
||||||
if (ifi < 0)
|
if (ifi < 0)
|
||||||
|
@ -560,16 +576,11 @@ int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to add netlink interface index: %m");
|
return log_error_errno(r, "Failed to add netlink interface index: %m");
|
||||||
|
|
||||||
n = strjoin("mv-", *i);
|
n = strdup(*b);
|
||||||
if (!n)
|
if (!n)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = shorten_ifname(n);
|
shortened = 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);
|
r = sd_netlink_message_append_string(m, IFLA_IFNAME, n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -607,27 +618,28 @@ int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to add new macvlan interfaces: %m");
|
return log_error_errno(r, "Failed to add new macvlan interfaces: %m");
|
||||||
|
|
||||||
(void) set_alternative_ifname(rtnl, n, a);
|
if (shortened > 0)
|
||||||
|
(void) set_alternative_ifname(rtnl, n, *b);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces) {
|
int setup_ipvlan(const char *machine_name, pid_t pid, char **iface_pairs) {
|
||||||
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (strv_isempty(ifaces))
|
if (strv_isempty(iface_pairs))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = sd_netlink_open(&rtnl);
|
r = sd_netlink_open(&rtnl);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to connect to netlink: %m");
|
return log_error_errno(r, "Failed to connect to netlink: %m");
|
||||||
|
|
||||||
STRV_FOREACH(i, ifaces) {
|
STRV_FOREACH_PAIR(i, b, iface_pairs) {
|
||||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||||
_cleanup_free_ char *n = NULL, *a = NULL;
|
_cleanup_free_ char *n = NULL;
|
||||||
int ifi;
|
int shortened, ifi ;
|
||||||
|
|
||||||
ifi = rtnl_resolve_interface_or_warn(&rtnl, *i);
|
ifi = rtnl_resolve_interface_or_warn(&rtnl, *i);
|
||||||
if (ifi < 0)
|
if (ifi < 0)
|
||||||
|
@ -641,16 +653,11 @@ int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to add netlink interface index: %m");
|
return log_error_errno(r, "Failed to add netlink interface index: %m");
|
||||||
|
|
||||||
n = strjoin("iv-", *i);
|
n = strdup(*b);
|
||||||
if (!n)
|
if (!n)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = shorten_ifname(n);
|
shortened = 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);
|
r = sd_netlink_message_append_string(m, IFLA_IFNAME, n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -684,7 +691,8 @@ int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to add new ipvlan interfaces: %m");
|
return log_error_errno(r, "Failed to add new ipvlan interfaces: %m");
|
||||||
|
|
||||||
(void) set_alternative_ifname(rtnl, n, a);
|
if (shortened > 0)
|
||||||
|
(void) set_alternative_ifname(rtnl, n, *b);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -742,3 +750,51 @@ int remove_veth_links(const char *primary, char **pairs) {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int network_iface_pair_parse(const char* iftype, char ***l, const char *p, const char* ifprefix) {
|
||||||
|
_cleanup_free_ char *a = NULL, *b = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = extract_first_word(&p, &a, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to extract first word in %s parameter: %m", iftype);
|
||||||
|
if (r == 0)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
|
"Short read while reading %s parameter: %m", iftype);
|
||||||
|
if (!ifname_valid(a))
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
|
"%s, interface name not valid: %s", iftype, a);
|
||||||
|
|
||||||
|
if (isempty(p)) {
|
||||||
|
if (ifprefix)
|
||||||
|
b = strjoin(ifprefix, a);
|
||||||
|
else
|
||||||
|
b = strdup(a);
|
||||||
|
} else
|
||||||
|
b = strdup(p);
|
||||||
|
if (!b)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
if (!ifname_valid(b))
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
|
"%s, interface name not valid: %s", iftype, b);
|
||||||
|
|
||||||
|
r = strv_push_pair(l, a, b);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
a = b = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int interface_pair_parse(char ***l, const char *p) {
|
||||||
|
return network_iface_pair_parse("Network interface", l, p, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int macvlan_pair_parse(char ***l, const char *p) {
|
||||||
|
return network_iface_pair_parse("MACVLAN network interface", l, p, "mv-");
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipvlan_pair_parse(char ***l, const char *p) {
|
||||||
|
return network_iface_pair_parse("IPVLAN network interface", l, p, "iv-");
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
int test_network_interface_initialized(const char *name);
|
int test_network_interfaces_initialized(char **iface_pairs);
|
||||||
|
|
||||||
int setup_veth(const char *machine_name, pid_t pid, char iface_name[IFNAMSIZ], bool bridge);
|
int setup_veth(const char *machine_name, pid_t pid, char iface_name[IFNAMSIZ], bool bridge);
|
||||||
int setup_veth_extra(const char *machine_name, pid_t pid, char **pairs);
|
int setup_veth_extra(const char *machine_name, pid_t pid, char **pairs);
|
||||||
|
@ -13,11 +13,15 @@ int setup_veth_extra(const char *machine_name, pid_t pid, char **pairs);
|
||||||
int setup_bridge(const char *veth_name, const char *bridge_name, bool create);
|
int setup_bridge(const char *veth_name, const char *bridge_name, bool create);
|
||||||
int remove_bridge(const char *bridge_name);
|
int remove_bridge(const char *bridge_name);
|
||||||
|
|
||||||
int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces);
|
int setup_macvlan(const char *machine_name, pid_t pid, char **iface_pairs);
|
||||||
int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces);
|
int setup_ipvlan(const char *machine_name, pid_t pid, char **iface_pairs);
|
||||||
|
|
||||||
int move_network_interfaces(int netns_fd, char **ifaces);
|
int move_network_interfaces(int netns_fd, char **iface_pairs);
|
||||||
|
|
||||||
int veth_extra_parse(char ***l, const char *p);
|
int veth_extra_parse(char ***l, const char *p);
|
||||||
|
|
||||||
int remove_veth_links(const char *primary, char **pairs);
|
int remove_veth_links(const char *primary, char **pairs);
|
||||||
|
|
||||||
|
int interface_pair_parse(char ***l, const char *p);
|
||||||
|
int macvlan_pair_parse(char ***l, const char *p);
|
||||||
|
int ipvlan_pair_parse(char ***l, const char *p);
|
||||||
|
|
|
@ -469,6 +469,69 @@ int config_parse_veth_extra(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int config_parse_network_iface_pair(
|
||||||
|
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*** l = data;
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
assert(lvalue);
|
||||||
|
assert(rvalue);
|
||||||
|
|
||||||
|
return interface_pair_parse(l, rvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
int config_parse_macvlan_iface_pair(
|
||||||
|
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*** l = data;
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
assert(lvalue);
|
||||||
|
assert(rvalue);
|
||||||
|
|
||||||
|
return macvlan_pair_parse(l, rvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
int config_parse_ipvlan_iface_pair(
|
||||||
|
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*** l = data;
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
assert(lvalue);
|
||||||
|
assert(rvalue);
|
||||||
|
|
||||||
|
return ipvlan_pair_parse(l, rvalue);
|
||||||
|
}
|
||||||
|
|
||||||
int config_parse_network_zone(
|
int config_parse_network_zone(
|
||||||
const char *unit,
|
const char *unit,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
|
|
|
@ -259,6 +259,9 @@ CONFIG_PARSER_PROTOTYPE(config_parse_tmpfs);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_overlay);
|
CONFIG_PARSER_PROTOTYPE(config_parse_overlay);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_inaccessible);
|
CONFIG_PARSER_PROTOTYPE(config_parse_inaccessible);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_veth_extra);
|
CONFIG_PARSER_PROTOTYPE(config_parse_veth_extra);
|
||||||
|
CONFIG_PARSER_PROTOTYPE(config_parse_network_iface_pair);
|
||||||
|
CONFIG_PARSER_PROTOTYPE(config_parse_macvlan_iface_pair);
|
||||||
|
CONFIG_PARSER_PROTOTYPE(config_parse_ipvlan_iface_pair);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_network_zone);
|
CONFIG_PARSER_PROTOTYPE(config_parse_network_zone);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_boot);
|
CONFIG_PARSER_PROTOTYPE(config_parse_boot);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_pid2);
|
CONFIG_PARSER_PROTOTYPE(config_parse_pid2);
|
||||||
|
|
|
@ -377,13 +377,13 @@ static int help(void) {
|
||||||
" --private-users-ownership=auto\n\n"
|
" --private-users-ownership=auto\n\n"
|
||||||
"%3$sNetworking:%4$s\n"
|
"%3$sNetworking:%4$s\n"
|
||||||
" --private-network Disable network in container\n"
|
" --private-network Disable network in container\n"
|
||||||
" --network-interface=INTERFACE\n"
|
" --network-interface=HOSTIF[:CONTAINERIF]\n"
|
||||||
" Assign an existing network interface to the\n"
|
" Assign an existing network interface to the\n"
|
||||||
" container\n"
|
" container\n"
|
||||||
" --network-macvlan=INTERFACE\n"
|
" --network-macvlan=HOSTIF[:CONTAINERIF]\n"
|
||||||
" Create a macvlan network interface based on an\n"
|
" Create a macvlan network interface based on an\n"
|
||||||
" existing network interface to the container\n"
|
" existing network interface to the container\n"
|
||||||
" --network-ipvlan=INTERFACE\n"
|
" --network-ipvlan=HOSTIF[:CONTAINERIF]\n"
|
||||||
" Create an ipvlan network interface based on an\n"
|
" Create an ipvlan network interface based on an\n"
|
||||||
" existing network interface to the container\n"
|
" existing network interface to the container\n"
|
||||||
" -n --network-veth Add a virtual Ethernet connection between host\n"
|
" -n --network-veth Add a virtual Ethernet connection between host\n"
|
||||||
|
@ -924,51 +924,28 @@ static int parse_argv(int argc, char *argv[]) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ARG_NETWORK_INTERFACE:
|
case ARG_NETWORK_INTERFACE:
|
||||||
if (!ifname_valid(optarg))
|
r = interface_pair_parse(&arg_network_interfaces, optarg);
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
||||||
"Network interface name not valid: %s", optarg);
|
|
||||||
|
|
||||||
r = test_network_interface_initialized(optarg);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (strv_extend(&arg_network_interfaces, optarg) < 0)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
arg_private_network = true;
|
arg_private_network = true;
|
||||||
arg_settings_mask |= SETTING_NETWORK;
|
arg_settings_mask |= SETTING_NETWORK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ARG_NETWORK_MACVLAN:
|
case ARG_NETWORK_MACVLAN:
|
||||||
|
r = macvlan_pair_parse(&arg_network_macvlan, optarg);
|
||||||
if (!ifname_valid(optarg))
|
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
||||||
"MACVLAN network interface name not valid: %s", optarg);
|
|
||||||
|
|
||||||
r = test_network_interface_initialized(optarg);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (strv_extend(&arg_network_macvlan, optarg) < 0)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
arg_private_network = true;
|
arg_private_network = true;
|
||||||
arg_settings_mask |= SETTING_NETWORK;
|
arg_settings_mask |= SETTING_NETWORK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ARG_NETWORK_IPVLAN:
|
case ARG_NETWORK_IPVLAN:
|
||||||
|
r = ipvlan_pair_parse(&arg_network_ipvlan, optarg);
|
||||||
if (!ifname_valid(optarg))
|
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
||||||
"IPVLAN network interface name not valid: %s", optarg);
|
|
||||||
|
|
||||||
r = test_network_interface_initialized(optarg);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (strv_extend(&arg_network_ipvlan, optarg) < 0)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
_fallthrough_;
|
_fallthrough_;
|
||||||
case ARG_PRIVATE_NETWORK:
|
case ARG_PRIVATE_NETWORK:
|
||||||
arg_private_network = true;
|
arg_private_network = true;
|
||||||
|
@ -1894,6 +1871,23 @@ static int verify_arguments(void) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int verify_network_interfaces_initialized(void) {
|
||||||
|
int r;
|
||||||
|
r = test_network_interfaces_initialized(arg_network_interfaces);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = test_network_interfaces_initialized(arg_network_macvlan);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = test_network_interfaces_initialized(arg_network_ipvlan);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int userns_lchown(const char *p, uid_t uid, gid_t gid) {
|
int userns_lchown(const char *p, uid_t uid, gid_t gid) {
|
||||||
assert(p);
|
assert(p);
|
||||||
|
|
||||||
|
@ -5288,6 +5282,10 @@ static int run_container(
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reverse network interfaces pair list so that interfaces get their initial name back.
|
||||||
|
* This is about ensuring interfaces get their old name back when being moved back. */
|
||||||
|
arg_network_interfaces = strv_reverse(arg_network_interfaces);
|
||||||
|
|
||||||
r = move_network_interfaces(parent_netns_fd, arg_network_interfaces);
|
r = move_network_interfaces(parent_netns_fd, arg_network_interfaces);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_error_errno(r, "Failed to move network interfaces back to parent network namespace: %m");
|
log_error_errno(r, "Failed to move network interfaces back to parent network namespace: %m");
|
||||||
|
@ -5506,6 +5504,10 @@ static int run(int argc, char *argv[]) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
|
r = verify_network_interfaces_initialized();
|
||||||
|
if (r < 0)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
/* Reapply environment settings. */
|
/* Reapply environment settings. */
|
||||||
(void) detect_unified_cgroup_hierarchy_from_environment();
|
(void) detect_unified_cgroup_hierarchy_from_environment();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue