3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-12-22 21:12:48 +01:00

manager: Fallback to old logic for some drivers

If we get an error during DEL_INTERFACE or NEW_INTERFACE we may be
dealing with a driver that doesn't implement virtual interfaces or
doesn't implement deleting the default interface.  In this case fall
back to using the first usable interface that we've detected on this
wiphy.

There's at least one full-mac driver that doesn't implement the cfg80211
.del_virtual_intf and .add_virtual_intf methods and at least one that
only allows P2P interfaces to be manipulated.  mac80211 drivers seem to
at least implement those methods but I didn't check to see if there are
driver where they'd eventually return EOPNOTSUPP.
This commit is contained in:
Andrew Zaborowski 2019-04-11 03:10:28 +02:00 committed by Denis Kenzior
parent 2ea9db9cae
commit 9e079ba4fc

View File

@ -48,6 +48,14 @@ struct wiphy_setup_state {
struct l_timeout *setup_timeout;
unsigned int pending_cmd_count;
bool aborted;
/*
* Data we may need if the driver does not seem to support interface
* manipulation and we fall back to using the driver-created default
* interface.
*/
bool use_default;
struct l_genl_msg *default_if_msg;
};
static struct l_queue *pending_wiphys;
@ -61,10 +69,29 @@ static void wiphy_setup_state_free(void *data)
if (state->setup_timeout)
l_timeout_remove(state->setup_timeout);
if (state->default_if_msg)
l_genl_msg_unref(state->default_if_msg);
L_WARN_ON(state->pending_cmd_count);
l_free(state);
}
static bool manager_use_default(struct wiphy_setup_state *state)
{
l_debug("");
if (!state->default_if_msg) {
l_error("No default interface for wiphy %u",
(unsigned int) state->id);
wiphy_setup_state_free(state);
return false;
}
netdev_create_from_genl(state->default_if_msg);
wiphy_setup_state_free(state);
return true;
}
static void manager_new_interface_cb(struct l_genl_msg *msg, void *user_data)
{
struct wiphy_setup_state *state = user_data;
@ -108,6 +135,11 @@ static void manager_create_interfaces(struct wiphy_setup_state *state)
return;
}
if (state->use_default) {
manager_use_default(state);
return;
}
/*
* Current policy: we maintain one netdev per wiphy for station,
* AP and Ad-Hoc modes, one optional p2p-device and zero or more
@ -158,9 +190,11 @@ static void manager_del_interface_cb(struct l_genl_msg *msg, void *user_data)
if (state->aborted)
return;
if (l_genl_msg_get_error(msg) < 0)
if (l_genl_msg_get_error(msg) < 0) {
l_error("DEL_INTERFACE failed: %s",
strerror(-l_genl_msg_get_error(msg)));
state->use_default = true;
}
}
static void manager_get_interface_cb(struct l_genl_msg *msg, void *user_data)
@ -236,6 +270,21 @@ static void manager_get_interface_cb(struct l_genl_msg *msg, void *user_data)
if (!ifindex || !wdev_idx || !iftype || !ifname)
return;
/*
* If this interface is usable as our default netdev in case the
* driver does not support interface manipulation, save the message
* just in case.
*/
if ((*iftype == NL80211_IFTYPE_ADHOC ||
*iftype == NL80211_IFTYPE_STATION ||
*iftype == NL80211_IFTYPE_AP) &&
ifindex && *ifindex != 0 &&
!state->default_if_msg)
state->default_if_msg = l_genl_msg_ref(msg);
if (state->use_default)
return;
del_msg = l_genl_msg_new(NL80211_CMD_DEL_INTERFACE);
l_genl_msg_append_attr(del_msg, NL80211_ATTR_IFINDEX, 4, ifindex);
l_genl_msg_append_attr(del_msg, NL80211_ATTR_WDEV, 8, wdev_idx);
@ -246,6 +295,7 @@ static void manager_get_interface_cb(struct l_genl_msg *msg, void *user_data)
if (!cmd_id) {
l_error("Sending DEL_INTERFACE for %s failed", ifname);
state->use_default = true;
return;
}