diff options
| author | Denis Kenzior <denkenz@gmail.com> | 2016-08-03 17:58:33 -0400 |
|---|---|---|
| committer | Johannes Berg <johannes.berg@intel.com> | 2016-08-11 10:51:41 -0400 |
| commit | 896ff0635a312022c91e2bef30c80abc27af62e8 (patch) | |
| tree | aa28f1eb1bbb97da2ef565117e79f8d51087cc56 /net/wireless | |
| parent | eae4430ee7c5ea1152400cfc070f3746d41fa134 (diff) | |
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: Denis Kenzior <denkenz@gmail.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
| -rw-r--r-- | net/wireless/core.c | 2 | ||||
| -rw-r--r-- | net/wireless/nl80211.c | 46 | ||||
| -rw-r--r-- | net/wireless/nl80211.h | 3 |
3 files changed, 37 insertions, 14 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c index 7645e97362c0..7758c0fe781a 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
| @@ -1079,6 +1079,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
| 1079 | wdev->iftype == NL80211_IFTYPE_P2P_CLIENT || | 1079 | wdev->iftype == NL80211_IFTYPE_P2P_CLIENT || |
| 1080 | wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr) | 1080 | wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr) |
| 1081 | dev->priv_flags |= IFF_DONT_BRIDGE; | 1081 | dev->priv_flags |= IFF_DONT_BRIDGE; |
| 1082 | |||
| 1083 | nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE); | ||
| 1082 | break; | 1084 | break; |
| 1083 | case NETDEV_GOING_DOWN: | 1085 | case NETDEV_GOING_DOWN: |
| 1084 | cfg80211_leave(rdev, wdev); | 1086 | cfg80211_leave(rdev, wdev); |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index f02653a08993..a8c062dbd51d 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -2751,7 +2751,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
| 2751 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 2751 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| 2752 | struct vif_params params; | 2752 | struct vif_params params; |
| 2753 | struct wireless_dev *wdev; | 2753 | struct wireless_dev *wdev; |
| 2754 | struct sk_buff *msg, *event; | 2754 | struct sk_buff *msg; |
| 2755 | int err; | 2755 | int err; |
| 2756 | enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED; | 2756 | enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED; |
| 2757 | u32 flags; | 2757 | u32 flags; |
| @@ -2855,20 +2855,15 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
| 2855 | return -ENOBUFS; | 2855 | return -ENOBUFS; |
| 2856 | } | 2856 | } |
| 2857 | 2857 | ||
| 2858 | event = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 2858 | /* |
| 2859 | if (event) { | 2859 | * For wdevs which have no associated netdev object (e.g. of type |
| 2860 | if (nl80211_send_iface(event, 0, 0, 0, | 2860 | * NL80211_IFTYPE_P2P_DEVICE), emit the NEW_INTERFACE event here. |
| 2861 | rdev, wdev, false) < 0) { | 2861 | * For all other types, the event will be generated from the |
| 2862 | nlmsg_free(event); | 2862 | * netdev notifier |
| 2863 | goto out; | 2863 | */ |
| 2864 | } | 2864 | if (!wdev->netdev) |
| 2865 | 2865 | nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE); | |
| 2866 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), | ||
| 2867 | event, 0, NL80211_MCGRP_CONFIG, | ||
| 2868 | GFP_KERNEL); | ||
| 2869 | } | ||
| 2870 | 2866 | ||
| 2871 | out: | ||
| 2872 | return genlmsg_reply(msg, info); | 2867 | return genlmsg_reply(msg, info); |
| 2873 | } | 2868 | } |
| 2874 | 2869 | ||
| @@ -11847,6 +11842,29 @@ void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev, | |||
| 11847 | NL80211_MCGRP_CONFIG, GFP_KERNEL); | 11842 | NL80211_MCGRP_CONFIG, GFP_KERNEL); |
| 11848 | } | 11843 | } |
| 11849 | 11844 | ||
| 11845 | void nl80211_notify_iface(struct cfg80211_registered_device *rdev, | ||
| 11846 | struct wireless_dev *wdev, | ||
| 11847 | enum nl80211_commands cmd) | ||
| 11848 | { | ||
| 11849 | struct sk_buff *msg; | ||
| 11850 | |||
| 11851 | WARN_ON(cmd != NL80211_CMD_NEW_INTERFACE && | ||
| 11852 | cmd != NL80211_CMD_DEL_INTERFACE); | ||
| 11853 | |||
| 11854 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
| 11855 | if (!msg) | ||
| 11856 | return; | ||
| 11857 | |||
| 11858 | if (nl80211_send_iface(msg, 0, 0, 0, rdev, wdev, | ||
| 11859 | cmd == NL80211_CMD_DEL_INTERFACE) < 0) { | ||
| 11860 | nlmsg_free(msg); | ||
| 11861 | return; | ||
| 11862 | } | ||
| 11863 | |||
| 11864 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, | ||
| 11865 | NL80211_MCGRP_CONFIG, GFP_KERNEL); | ||
| 11866 | } | ||
| 11867 | |||
| 11850 | static int nl80211_add_scan_req(struct sk_buff *msg, | 11868 | static int nl80211_add_scan_req(struct sk_buff *msg, |
| 11851 | struct cfg80211_registered_device *rdev) | 11869 | struct cfg80211_registered_device *rdev) |
| 11852 | { | 11870 | { |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index a63f402b10b7..7e3821d7fcc5 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
| @@ -7,6 +7,9 @@ int nl80211_init(void); | |||
| 7 | void nl80211_exit(void); | 7 | void nl80211_exit(void); |
| 8 | void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev, | 8 | void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev, |
| 9 | enum nl80211_commands cmd); | 9 | enum nl80211_commands cmd); |
| 10 | void nl80211_notify_iface(struct cfg80211_registered_device *rdev, | ||
| 11 | struct wireless_dev *wdev, | ||
| 12 | enum nl80211_commands cmd); | ||
| 10 | void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, | 13 | void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, |
| 11 | struct wireless_dev *wdev); | 14 | struct wireless_dev *wdev); |
| 12 | struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev, | 15 | struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev, |
