Commit 896ff063 authored by Denis Kenzior's avatar Denis Kenzior Committed by Johannes Berg

cfg80211: always notify userspace of new wireless netdevs

This change alters the semantics of NL80211_CMD_NEW_INTERFACE events
by always sending this event whenever a new net_device object
associated with a wdev is registered.  Prior to this change, this event
was only sent as a result of NL80211_CMD_NEW_INTERFACE command sent
from userspace.  This allows userspace to reliably detect new wireless
interfaces (e.g. due to hardware hot-plug events, etc).

For wdevs created without an associated net_device object (e.g.
NL80211_IFTYPE_P2P_DEVICE), the NL80211_CMD_NEW_INTERFACE event is
still generated inside the relevant nl80211 command handler.
Signed-off-by: default avatarDenis Kenzior <denkenz@gmail.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent eae4430e
...@@ -1079,6 +1079,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, ...@@ -1079,6 +1079,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
wdev->iftype == NL80211_IFTYPE_P2P_CLIENT || wdev->iftype == NL80211_IFTYPE_P2P_CLIENT ||
wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr) wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
dev->priv_flags |= IFF_DONT_BRIDGE; dev->priv_flags |= IFF_DONT_BRIDGE;
nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
break; break;
case NETDEV_GOING_DOWN: case NETDEV_GOING_DOWN:
cfg80211_leave(rdev, wdev); cfg80211_leave(rdev, wdev);
......
...@@ -2751,7 +2751,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) ...@@ -2751,7 +2751,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct vif_params params; struct vif_params params;
struct wireless_dev *wdev; struct wireless_dev *wdev;
struct sk_buff *msg, *event; struct sk_buff *msg;
int err; int err;
enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED; enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
u32 flags; u32 flags;
...@@ -2855,20 +2855,15 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) ...@@ -2855,20 +2855,15 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
return -ENOBUFS; return -ENOBUFS;
} }
event = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); /*
if (event) { * For wdevs which have no associated netdev object (e.g. of type
if (nl80211_send_iface(event, 0, 0, 0, * NL80211_IFTYPE_P2P_DEVICE), emit the NEW_INTERFACE event here.
rdev, wdev, false) < 0) { * For all other types, the event will be generated from the
nlmsg_free(event); * netdev notifier
goto out; */
} if (!wdev->netdev)
nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
event, 0, NL80211_MCGRP_CONFIG,
GFP_KERNEL);
}
out:
return genlmsg_reply(msg, info); return genlmsg_reply(msg, info);
} }
...@@ -11847,6 +11842,29 @@ void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev, ...@@ -11847,6 +11842,29 @@ void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
NL80211_MCGRP_CONFIG, GFP_KERNEL); NL80211_MCGRP_CONFIG, GFP_KERNEL);
} }
void nl80211_notify_iface(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
enum nl80211_commands cmd)
{
struct sk_buff *msg;
WARN_ON(cmd != NL80211_CMD_NEW_INTERFACE &&
cmd != NL80211_CMD_DEL_INTERFACE);
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg)
return;
if (nl80211_send_iface(msg, 0, 0, 0, rdev, wdev,
cmd == NL80211_CMD_DEL_INTERFACE) < 0) {
nlmsg_free(msg);
return;
}
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
NL80211_MCGRP_CONFIG, GFP_KERNEL);
}
static int nl80211_add_scan_req(struct sk_buff *msg, static int nl80211_add_scan_req(struct sk_buff *msg,
struct cfg80211_registered_device *rdev) struct cfg80211_registered_device *rdev)
{ {
......
...@@ -7,6 +7,9 @@ int nl80211_init(void); ...@@ -7,6 +7,9 @@ int nl80211_init(void);
void nl80211_exit(void); void nl80211_exit(void);
void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev, void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
enum nl80211_commands cmd); enum nl80211_commands cmd);
void nl80211_notify_iface(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
enum nl80211_commands cmd);
void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev); struct wireless_dev *wdev);
struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev, struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment