aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorTomasz Bursztyka <tomasz.bursztyka@linux.intel.com>2014-11-12 09:26:45 -0500
committerJohannes Berg <johannes.berg@intel.com>2014-11-19 13:02:42 -0500
commit8f894be2df9ad43d17763bc0201f7f303a91f091 (patch)
treebf19c754c4f1c6c168ff31a0cb3d4f3e7e2b7976 /net/wireless
parent93d638d49cac96a93abf09bb3526f2112d9f8387 (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.c48
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
2346static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, 2346static 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
2714out:
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
2721static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info) 2755static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)