diff options
author | Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com> | 2014-11-12 09:26:45 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-11-19 13:02:42 -0500 |
commit | 8f894be2df9ad43d17763bc0201f7f303a91f091 (patch) | |
tree | bf19c754c4f1c6c168ff31a0cb3d4f3e7e2b7976 /net/wireless | |
parent | 93d638d49cac96a93abf09bb3526f2112d9f8387 (diff) |
nl80211: Broadcast CMD_NEW_INTERFACE and CMD_DEL_INTERFACE
Let the other listeners being notified when a new or del interface
command has been issued, thus reducing later necessary request to be in
sync with current context.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/nl80211.c | 48 |
1 files changed, 41 insertions, 7 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c81491b1f737..6e4177701d86 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -2345,12 +2345,16 @@ static int nl80211_send_chandef(struct sk_buff *msg, | |||
2345 | 2345 | ||
2346 | static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, | 2346 | static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, |
2347 | struct cfg80211_registered_device *rdev, | 2347 | struct cfg80211_registered_device *rdev, |
2348 | struct wireless_dev *wdev) | 2348 | struct wireless_dev *wdev, bool removal) |
2349 | { | 2349 | { |
2350 | struct net_device *dev = wdev->netdev; | 2350 | struct net_device *dev = wdev->netdev; |
2351 | u8 cmd = NL80211_CMD_NEW_INTERFACE; | ||
2351 | void *hdr; | 2352 | void *hdr; |
2352 | 2353 | ||
2353 | hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_INTERFACE); | 2354 | if (removal) |
2355 | cmd = NL80211_CMD_DEL_INTERFACE; | ||
2356 | |||
2357 | hdr = nl80211hdr_put(msg, portid, seq, flags, cmd); | ||
2354 | if (!hdr) | 2358 | if (!hdr) |
2355 | return -1; | 2359 | return -1; |
2356 | 2360 | ||
@@ -2417,7 +2421,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * | |||
2417 | } | 2421 | } |
2418 | if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid, | 2422 | if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid, |
2419 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 2423 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
2420 | rdev, wdev) < 0) { | 2424 | rdev, wdev, false) < 0) { |
2421 | goto out; | 2425 | goto out; |
2422 | } | 2426 | } |
2423 | if_idx++; | 2427 | if_idx++; |
@@ -2445,7 +2449,7 @@ static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info) | |||
2445 | return -ENOMEM; | 2449 | return -ENOMEM; |
2446 | 2450 | ||
2447 | if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0, | 2451 | if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0, |
2448 | rdev, wdev) < 0) { | 2452 | rdev, wdev, false) < 0) { |
2449 | nlmsg_free(msg); | 2453 | nlmsg_free(msg); |
2450 | return -ENOBUFS; | 2454 | return -ENOBUFS; |
2451 | } | 2455 | } |
@@ -2591,7 +2595,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
2591 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 2595 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
2592 | struct vif_params params; | 2596 | struct vif_params params; |
2593 | struct wireless_dev *wdev; | 2597 | struct wireless_dev *wdev; |
2594 | struct sk_buff *msg; | 2598 | struct sk_buff *msg, *event; |
2595 | int err; | 2599 | int err; |
2596 | enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED; | 2600 | enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED; |
2597 | u32 flags; | 2601 | u32 flags; |
@@ -2689,11 +2693,25 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
2689 | } | 2693 | } |
2690 | 2694 | ||
2691 | if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0, | 2695 | if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0, |
2692 | rdev, wdev) < 0) { | 2696 | rdev, wdev, false) < 0) { |
2693 | nlmsg_free(msg); | 2697 | nlmsg_free(msg); |
2694 | return -ENOBUFS; | 2698 | return -ENOBUFS; |
2695 | } | 2699 | } |
2696 | 2700 | ||
2701 | event = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
2702 | if (event) { | ||
2703 | if (nl80211_send_iface(event, 0, 0, 0, | ||
2704 | rdev, wdev, false) < 0) { | ||
2705 | nlmsg_free(event); | ||
2706 | goto out; | ||
2707 | } | ||
2708 | |||
2709 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), | ||
2710 | event, 0, NL80211_MCGRP_CONFIG, | ||
2711 | GFP_KERNEL); | ||
2712 | } | ||
2713 | |||
2714 | out: | ||
2697 | return genlmsg_reply(msg, info); | 2715 | return genlmsg_reply(msg, info); |
2698 | } | 2716 | } |
2699 | 2717 | ||
@@ -2701,10 +2719,18 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) | |||
2701 | { | 2719 | { |
2702 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 2720 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
2703 | struct wireless_dev *wdev = info->user_ptr[1]; | 2721 | struct wireless_dev *wdev = info->user_ptr[1]; |
2722 | struct sk_buff *msg; | ||
2723 | int status; | ||
2704 | 2724 | ||
2705 | if (!rdev->ops->del_virtual_intf) | 2725 | if (!rdev->ops->del_virtual_intf) |
2706 | return -EOPNOTSUPP; | 2726 | return -EOPNOTSUPP; |
2707 | 2727 | ||
2728 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
2729 | if (msg && nl80211_send_iface(msg, 0, 0, 0, rdev, wdev, true) < 0) { | ||
2730 | nlmsg_free(msg); | ||
2731 | msg = NULL; | ||
2732 | } | ||
2733 | |||
2708 | /* | 2734 | /* |
2709 | * If we remove a wireless device without a netdev then clear | 2735 | * If we remove a wireless device without a netdev then clear |
2710 | * user_ptr[1] so that nl80211_post_doit won't dereference it | 2736 | * user_ptr[1] so that nl80211_post_doit won't dereference it |
@@ -2715,7 +2741,15 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) | |||
2715 | if (!wdev->netdev) | 2741 | if (!wdev->netdev) |
2716 | info->user_ptr[1] = NULL; | 2742 | info->user_ptr[1] = NULL; |
2717 | 2743 | ||
2718 | return rdev_del_virtual_intf(rdev, wdev); | 2744 | status = rdev_del_virtual_intf(rdev, wdev); |
2745 | if (status >= 0 && msg) | ||
2746 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), | ||
2747 | msg, 0, NL80211_MCGRP_CONFIG, | ||
2748 | GFP_KERNEL); | ||
2749 | else | ||
2750 | nlmsg_free(msg); | ||
2751 | |||
2752 | return status; | ||
2719 | } | 2753 | } |
2720 | 2754 | ||
2721 | static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info) | 2755 | static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info) |