lxc_log_define(network, lxc);
typedef int (*instantiate_cb)(struct lxc_handler *, struct lxc_netdev *);
+typedef int (*instantiate_ns_cb)(struct lxc_netdev *);
static const char loop_device[] = "lo";
static int lxc_ip_route_dest(__u16 nlmsg_type, int family, int ifindex, void *dest, unsigned int netmask)
}
strlcpy(netdev->created_name, peer, IFNAMSIZ);
+ if (netdev->name[0] == '\0')
+ (void)strlcpy(netdev->name, peer, IFNAMSIZ);
netdev->ifindex = if_nametoindex(peer);
if (!netdev->ifindex) {
}
strlcpy(netdev->created_name, peer, IFNAMSIZ);
+ if (netdev->name[0] == '\0')
+ (void)strlcpy(netdev->name, peer, IFNAMSIZ);
netdev->ifindex = if_nametoindex(peer);
if (!netdev->ifindex) {
}
strlcpy(netdev->created_name, peer, IFNAMSIZ);
+ if (netdev->name[0] == '\0')
+ (void)strlcpy(netdev->name, peer, IFNAMSIZ);
netdev->ifindex = if_nametoindex(peer);
if (!netdev->ifindex) {
}
strlcpy(netdev->created_name, netdev->link, IFNAMSIZ);
+ if (netdev->name[0] == '\0')
+ (void)strlcpy(netdev->name, netdev->link, IFNAMSIZ);
/*
* Store the ifindex of the host's network device in the host's
[LXC_NET_NONE] = instantiate_none,
};
+static int instantiate_ns_veth(struct lxc_netdev *netdev)
+{
+ char current_ifname[IFNAMSIZ];
+
+ netdev->ifindex = if_nametoindex(netdev->created_name);
+ if (!netdev->ifindex)
+ return log_error_errno(-1,
+ errno, "Failed to retrieve ifindex for network device with name %s",
+ netdev->created_name);
+
+ if (netdev->name[0] == '\0')
+ (void)strlcpy(netdev->name, "eth%d", IFNAMSIZ);
+
+ if (strcmp(netdev->created_name, netdev->name) != 0) {
+ int ret;
+
+ ret = lxc_netdev_rename_by_name(netdev->created_name, netdev->name);
+ if (ret)
+ return log_error_errno(-1,
+ -ret, "Failed to rename network device \"%s\" to \"%s\"",
+ netdev->created_name,
+ netdev->name);
+
+ TRACE("Renamed network device from \"%s\" to \"%s\"", netdev->created_name, netdev->name);
+ }
+
+ /*
+ * Re-read the name of the interface because its name has changed and
+ * would be automatically allocated by the system
+ */
+ if (!if_indextoname(netdev->ifindex, current_ifname))
+ return log_error_errno(-1,
+ errno, "Failed get name for network device with ifindex %d",
+ netdev->ifindex);
+
+ /*
+ * Now update the recorded name of the network device to reflect the
+ * name of the network device in the child's network namespace. We will
+ * later on send this information back to the parent.
+ */
+ (void)strlcpy(netdev->name, current_ifname, IFNAMSIZ);
+
+ return 0;
+}
+
+static int __instantiate_common(struct lxc_netdev *netdev)
+{
+ netdev->ifindex = if_nametoindex(netdev->name);
+ if (!netdev->ifindex)
+ return log_error_errno(-1,
+ errno, "Failed to retrieve ifindex for network device with name %s",
+ netdev->name);
+
+ return 0;
+}
+
+static int instantiate_ns_macvlan(struct lxc_netdev *netdev)
+{
+ return __instantiate_common(netdev);
+}
+
+static int instantiate_ns_ipvlan(struct lxc_netdev *netdev)
+{
+ return __instantiate_common(netdev);
+}
+
+static int instantiate_ns_vlan(struct lxc_netdev *netdev)
+{
+ return __instantiate_common(netdev);
+}
+
+static int instantiate_ns_phys(struct lxc_netdev *netdev)
+{
+ return __instantiate_common(netdev);
+}
+
+static int instantiate_ns_empty(struct lxc_netdev *netdev)
+{
+ return 0;
+}
+
+static int instantiate_ns_none(struct lxc_netdev *netdev)
+{
+ return 0;
+}
+
+static instantiate_ns_cb netdev_ns_conf[LXC_NET_MAXCONFTYPE + 1] = {
+ [LXC_NET_VETH] = instantiate_ns_veth,
+ [LXC_NET_MACVLAN] = instantiate_ns_macvlan,
+ [LXC_NET_IPVLAN] = instantiate_ns_ipvlan,
+ [LXC_NET_VLAN] = instantiate_ns_vlan,
+ [LXC_NET_PHYS] = instantiate_ns_phys,
+ [LXC_NET_EMPTY] = instantiate_ns_empty,
+ [LXC_NET_NONE] = instantiate_ns_none,
+};
+
static int shutdown_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
{
int ret;
if (physname)
ret = lxc_netdev_move_wlan(physname, netdev->link, pid, NULL);
else
- ret = lxc_netdev_move_by_index(netdev->ifindex, pid, NULL);
+ ret = lxc_netdev_move_by_index(netdev->ifindex, pid, netdev->name);
if (ret) {
errno = -ret;
SYSERROR("Failed to move network device \"%s\" with ifindex %d to network namespace %d",
return 0;
}
-static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
+static int lxc_network_setup_in_child_namespaces_common(struct lxc_netdev *netdev)
{
- char ifname[IFNAMSIZ];
int err;
- char *current_ifname = ifname;
char bufinet4[INET_ADDRSTRLEN], bufinet6[INET6_ADDRSTRLEN];
/* empty network namespace */
- if (!netdev->ifindex) {
- if (netdev->flags & IFF_UP) {
- err = lxc_netdev_up("lo");
- if (err) {
- errno = -err;
- SYSERROR("Failed to set the loopback network device up");
- return -1;
- }
- }
-
- if (netdev->type == LXC_NET_EMPTY)
- return 0;
-
- if (netdev->type == LXC_NET_NONE)
- return 0;
-
- netdev->ifindex = if_nametoindex(netdev->created_name);
- if (!netdev->ifindex)
- SYSERROR("Failed to retrieve ifindex for network device with name %s",
- netdev->created_name ?: "(null)");
- }
-
- /* get the new ifindex in case of physical netdev */
- if (netdev->type == LXC_NET_PHYS) {
- netdev->ifindex = if_nametoindex(netdev->link);
- if (!netdev->ifindex) {
- ERROR("Failed to get ifindex for network device \"%s\"",
- netdev->link);
- return -1;
- }
- }
-
- /* retrieve the name of the interface */
- if (!if_indextoname(netdev->ifindex, current_ifname)) {
- SYSERROR("Failed to retrieve name for network device with ifindex %d",
- netdev->ifindex);
- return -1;
- }
-
- /* Default: let the system choose an interface name.
- * When the IFLA_IFNAME attribute is passed something like "<prefix>%d"
- * netlink will replace the format specifier with an appropriate index.
- */
- if (netdev->name[0] == '\0') {
- if (netdev->type == LXC_NET_PHYS)
- (void)strlcpy(netdev->name, netdev->link, IFNAMSIZ);
- else
- (void)strlcpy(netdev->name, "eth%d", IFNAMSIZ);
- }
-
- /* rename the interface name */
- if (strcmp(current_ifname, netdev->name) != 0) {
- err = lxc_netdev_rename_by_name(current_ifname, netdev->name);
+ if (!netdev->ifindex && netdev->flags & IFF_UP) {
+ err = lxc_netdev_up("lo");
if (err) {
errno = -err;
- SYSERROR("Failed to rename network device \"%s\" to \"%s\"",
- current_ifname, netdev->name);
+ SYSERROR( "Failed to set the loopback network device up");
return -1;
}
-
- TRACE("Renamed network device from \"%s\" to \"%s\"",
- current_ifname, netdev->name);
- }
-
- /* Re-read the name of the interface because its name has changed
- * and would be automatically allocated by the system
- */
- if (!if_indextoname(netdev->ifindex, current_ifname)) {
- ERROR("Failed get name for network device with ifindex %d",
- netdev->ifindex);
- return -1;
}
- /* Now update the recorded name of the network device to reflect the
- * name of the network device in the child's network namespace. We will
- * later on send this information back to the parent.
- */
- (void)strlcpy(netdev->name, current_ifname, IFNAMSIZ);
-
/* set a mac address */
if (netdev->hwaddr) {
- if (setup_hw_addr(netdev->hwaddr, current_ifname)) {
+ if (setup_hw_addr(netdev->hwaddr, netdev->name)) {
ERROR("Failed to setup hw address for network device \"%s\"",
- current_ifname);
+ netdev->name);
return -1;
}
}
/* setup ipv4 addresses on the interface */
if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) {
ERROR("Failed to setup ip addresses for network device \"%s\"",
- current_ifname);
+ netdev->name);
return -1;
}
/* setup ipv6 addresses on the interface */
if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) {
ERROR("Failed to setup ipv6 addresses for network device \"%s\"",
- current_ifname);
+ netdev->name);
return -1;
}
/* set the network device up */
if (netdev->flags & IFF_UP) {
- err = lxc_netdev_up(current_ifname);
+ err = lxc_netdev_up(netdev->name);
if (err) {
errno = -err;
SYSERROR("Failed to set network device \"%s\" up",
- current_ifname);
+ netdev->name);
return -1;
}
if (netdev->ipv4_gateway || netdev->ipv4_gateway_dev) {
if (!(netdev->flags & IFF_UP)) {
ERROR("Cannot add ipv4 gateway for network device "
- "\"%s\" when not bringing up the interface", current_ifname);
+ "\"%s\" when not bringing up the interface", netdev->name);
return -1;
}
if (lxc_list_empty(&netdev->ipv4)) {
ERROR("Cannot add ipv4 gateway for network device "
- "\"%s\" when not assigning an address", current_ifname);
+ "\"%s\" when not assigning an address", netdev->name);
return -1;
}
err = lxc_ipv4_gateway_add(netdev->ifindex, NULL);
if (err < 0) {
SYSERROR("Failed to setup ipv4 gateway to network device \"%s\"",
- current_ifname);
+ netdev->name);
return ret_set_errno(-1, -err);
}
} else {
if (err < 0) {
errno = -err;
SYSERROR("Failed to add ipv4 dest \"%s\" for network device \"%s\"",
- bufinet4, current_ifname);
+ bufinet4, netdev->name);
return -1;
}
if (err < 0) {
errno = -err;
SYSERROR("Failed to setup ipv4 gateway \"%s\" for network device \"%s\"",
- bufinet4, current_ifname);
+ bufinet4, netdev->name);
return -1;
}
}
if (netdev->ipv6_gateway || netdev->ipv6_gateway_dev) {
if (!(netdev->flags & IFF_UP)) {
ERROR("Cannot add ipv6 gateway for network device \"%s\" when not bringing up the interface",
- current_ifname);
+ netdev->name);
return -1;
}
if (lxc_list_empty(&netdev->ipv6) && !IN6_IS_ADDR_LINKLOCAL(netdev->ipv6_gateway)) {
ERROR("Cannot add ipv6 gateway for network device \"%s\" when not assigning an address",
- current_ifname);
+ netdev->name);
return -1;
}
err = lxc_ipv6_gateway_add(netdev->ifindex, NULL);
if (err < 0) {
SYSERROR("Failed to setup ipv6 gateway to network device \"%s\"",
- current_ifname);
+ netdev->name);
return ret_set_errno(-1, -err);
}
} else {
if (err < 0) {
errno = -err;
SYSERROR("Failed to add ipv6 dest \"%s\" for network device \"%s\"",
- bufinet6, current_ifname);
+ bufinet6, netdev->name);
return -1;
}
if (err < 0) {
errno = -err;
SYSERROR("Failed to setup ipv6 gateway \"%s\" for network device \"%s\"",
- bufinet6, current_ifname);
+ bufinet6, netdev->name);
return -1;
}
}
}
}
- DEBUG("Network device \"%s\" has been setup", current_ifname);
+ DEBUG("Network device \"%s\" has been setup", netdev->name);
return 0;
}
{
struct lxc_list *iterator;
- lxc_list_for_each(iterator, network) {
+ lxc_list_for_each (iterator, network) {
struct lxc_netdev *netdev = iterator->elem;
+ int ret;
- if (lxc_setup_netdev_in_child_namespaces(netdev)) {
+ ret = netdev_ns_conf[netdev->type](netdev);
+ if (!ret)
+ ret = lxc_network_setup_in_child_namespaces_common(netdev);
+ if (ret) {
ERROR("Failed to setup netdev");
return -1;
}