network/netdev: also check ifindex, iftype, and kind when assigning NetDev to Link
Even when a NetDev object with the same name found, its iftype or kind may be different. For safety, let's also check them.
This commit is contained in:
@@ -266,6 +266,43 @@ int netdev_get(Manager *manager, const char *name, NetDev **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void link_assign_netdev(Link *link) {
|
||||
_unused_ _cleanup_(netdev_unrefp) NetDev *old = NULL;
|
||||
NetDev *netdev;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(link->ifname);
|
||||
|
||||
old = TAKE_PTR(link->netdev);
|
||||
|
||||
if (netdev_get(link->manager, link->ifname, &netdev) < 0)
|
||||
return;
|
||||
|
||||
if (netdev->ifindex != link->ifindex)
|
||||
return;
|
||||
|
||||
if (NETDEV_VTABLE(netdev)->iftype != link->iftype)
|
||||
return;
|
||||
|
||||
if (!NETDEV_VTABLE(netdev)->skip_netdev_kind_check) {
|
||||
const char *kind;
|
||||
|
||||
if (netdev->kind == NETDEV_KIND_TAP)
|
||||
kind = "tun"; /* the kernel does not distinguish between tun and tap */
|
||||
else
|
||||
kind = netdev_kind_to_string(netdev->kind);
|
||||
|
||||
if (!streq_ptr(kind, link->kind))
|
||||
return;
|
||||
}
|
||||
|
||||
link->netdev = netdev_ref(netdev);
|
||||
|
||||
if (netdev != old)
|
||||
log_link_debug(link, "Found matching .netdev file: %s", netdev->filename);
|
||||
}
|
||||
|
||||
void netdev_enter_failed(NetDev *netdev) {
|
||||
netdev->state = NETDEV_STATE_FAILED;
|
||||
}
|
||||
|
||||
@@ -207,6 +207,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_unref);
|
||||
|
||||
bool netdev_is_managed(NetDev *netdev);
|
||||
int netdev_get(Manager *manager, const char *name, NetDev **ret);
|
||||
void link_assign_netdev(Link *link);
|
||||
int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *newlink);
|
||||
int netdev_generate_hw_addr(NetDev *netdev, Link *link, const char *name,
|
||||
const struct hw_addr_data *hw_addr, struct hw_addr_data *ret);
|
||||
|
||||
@@ -1307,18 +1307,15 @@ static int link_get_network(Link *link, Network **ret) {
|
||||
|
||||
int link_reconfigure_impl(Link *link, bool force) {
|
||||
Network *network = NULL;
|
||||
NetDev *netdev = NULL;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
link_assign_netdev(link);
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_LINGER))
|
||||
return 0;
|
||||
|
||||
r = netdev_get(link->manager, link->ifname, &netdev);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return r;
|
||||
|
||||
r = link_get_network(link, &network);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return r;
|
||||
@@ -1383,9 +1380,6 @@ int link_reconfigure_impl(Link *link, bool force) {
|
||||
link_free_engines(link);
|
||||
link->network = network_unref(link->network);
|
||||
|
||||
netdev_unref(link->netdev);
|
||||
link->netdev = netdev_ref(netdev);
|
||||
|
||||
if (!network) {
|
||||
link_set_state(link, LINK_STATE_UNMANAGED);
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user