diff options
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/core.c | 12 | ||||
-rw-r--r-- | net/wireless/core.h | 2 | ||||
-rw-r--r-- | net/wireless/ibss.c | 2 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 120 | ||||
-rw-r--r-- | net/wireless/reg.c | 6 | ||||
-rw-r--r-- | net/wireless/scan.c | 2 | ||||
-rw-r--r-- | net/wireless/sme.c | 6 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 42 | ||||
-rw-r--r-- | net/wireless/wext-core.c | 3 |
9 files changed, 185 insertions, 10 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c index fe6f402..c2a2c56 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -45,6 +45,9 @@ DEFINE_MUTEX(cfg80211_mutex); /* for debugfs */ static struct dentry *ieee80211_debugfs_dir; +/* for the cleanup, scan and event works */ +struct workqueue_struct *cfg80211_wq; + /* requires cfg80211_mutex to be held! */ struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx) { @@ -727,7 +730,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, break; case NETDEV_DOWN: dev_hold(dev); - schedule_work(&wdev->cleanup_work); + queue_work(cfg80211_wq, &wdev->cleanup_work); break; case NETDEV_UP: /* @@ -845,8 +848,14 @@ static int __init cfg80211_init(void) if (err) goto out_fail_reg; + cfg80211_wq = create_singlethread_workqueue("cfg80211"); + if (!cfg80211_wq) + goto out_fail_wq; + return 0; +out_fail_wq: + regulatory_exit(); out_fail_reg: debugfs_remove(ieee80211_debugfs_dir); out_fail_nl80211: @@ -868,5 +877,6 @@ static void cfg80211_exit(void) wiphy_sysfs_exit(); regulatory_exit(); unregister_pernet_device(&cfg80211_pernet_ops); + destroy_workqueue(cfg80211_wq); } module_exit(cfg80211_exit); diff --git a/net/wireless/core.h b/net/wireless/core.h index a9db9e6..4ef3efc 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -91,6 +91,8 @@ bool wiphy_idx_valid(int wiphy_idx) return (wiphy_idx >= 0); } + +extern struct workqueue_struct *cfg80211_wq; extern struct mutex cfg80211_mutex; extern struct list_head cfg80211_rdev_list; extern int cfg80211_rdev_list_generation; diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 34dfc93..6ef5a49 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -70,7 +70,7 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp) spin_lock_irqsave(&wdev->event_lock, flags); list_add_tail(&ev->list, &wdev->event_list); spin_unlock_irqrestore(&wdev->event_lock, flags); - schedule_work(&rdev->event_work); + queue_work(cfg80211_wq, &rdev->event_work); } EXPORT_SYMBOL(cfg80211_ibss_joined); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 149539a..a602843 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -139,6 +139,8 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, [NL80211_ATTR_PID] = { .type = NLA_U32 }, [NL80211_ATTR_4ADDR] = { .type = NLA_U8 }, + [NL80211_ATTR_PMKID] = { .type = NLA_BINARY, + .len = WLAN_PMKID_LEN }, }; /* policy for the attributes */ @@ -450,6 +452,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, sizeof(u32) * dev->wiphy.n_cipher_suites, dev->wiphy.cipher_suites); + NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_PMKIDS, + dev->wiphy.max_num_pmkids); + nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); if (!nl_modes) goto nla_put_failure; @@ -561,6 +566,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, CMD(deauth, DEAUTHENTICATE); CMD(disassoc, DISASSOCIATE); CMD(join_ibss, JOIN_IBSS); + CMD(set_pmksa, SET_PMKSA); + CMD(del_pmksa, DEL_PMKSA); + CMD(flush_pmksa, FLUSH_PMKSA); if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { i++; NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); @@ -4221,6 +4229,99 @@ static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info) return err; } +static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev; + int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_pmksa *pmksa) = NULL; + int err; + struct net_device *dev; + struct cfg80211_pmksa pmksa; + + memset(&pmksa, 0, sizeof(struct cfg80211_pmksa)); + + if (!info->attrs[NL80211_ATTR_MAC]) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_PMKID]) + return -EINVAL; + + rtnl_lock(); + + err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); + if (err) + goto out_rtnl; + + pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]); + pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); + + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { + err = -EOPNOTSUPP; + goto out; + } + + switch (info->genlhdr->cmd) { + case NL80211_CMD_SET_PMKSA: + rdev_ops = rdev->ops->set_pmksa; + break; + case NL80211_CMD_DEL_PMKSA: + rdev_ops = rdev->ops->del_pmksa; + break; + default: + WARN_ON(1); + break; + } + + if (!rdev_ops) { + err = -EOPNOTSUPP; + goto out; + } + + err = rdev_ops(&rdev->wiphy, dev, &pmksa); + + out: + cfg80211_unlock_rdev(rdev); + dev_put(dev); + out_rtnl: + rtnl_unlock(); + + return err; +} + +static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev; + int err; + struct net_device *dev; + + rtnl_lock(); + + err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); + if (err) + goto out_rtnl; + + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { + err = -EOPNOTSUPP; + goto out; + } + + if (!rdev->ops->flush_pmksa) { + err = -EOPNOTSUPP; + goto out; + } + + err = rdev->ops->flush_pmksa(&rdev->wiphy, dev); + + out: + cfg80211_unlock_rdev(rdev); + dev_put(dev); + out_rtnl: + rtnl_unlock(); + + return err; + +} + static struct genl_ops nl80211_ops[] = { { .cmd = NL80211_CMD_GET_WIPHY, @@ -4465,6 +4566,25 @@ static struct genl_ops nl80211_ops[] = { .policy = nl80211_policy, .dumpit = nl80211_dump_survey, }, + { + .cmd = NL80211_CMD_SET_PMKSA, + .doit = nl80211_setdel_pmksa, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = NL80211_CMD_DEL_PMKSA, + .doit = nl80211_setdel_pmksa, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = NL80211_CMD_FLUSH_PMKSA, + .doit = nl80211_flush_pmksa, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, + }; static struct genl_multicast_group nl80211_mlme_mcgrp = { .name = "mlme", diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 1f33017..c01470e 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1931,7 +1931,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) const struct ieee80211_freq_range *freq_range = NULL; const struct ieee80211_power_rule *power_rule = NULL; - printk(KERN_INFO "\t(start_freq - end_freq @ bandwidth), " + printk(KERN_INFO " (start_freq - end_freq @ bandwidth), " "(max_antenna_gain, max_eirp)\n"); for (i = 0; i < rd->n_reg_rules; i++) { @@ -1944,7 +1944,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) * in certain regions */ if (power_rule->max_antenna_gain) - printk(KERN_INFO "\t(%d KHz - %d KHz @ %d KHz), " + printk(KERN_INFO " (%d KHz - %d KHz @ %d KHz), " "(%d mBi, %d mBm)\n", freq_range->start_freq_khz, freq_range->end_freq_khz, @@ -1952,7 +1952,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) power_rule->max_antenna_gain, power_rule->max_eirp); else - printk(KERN_INFO "\t(%d KHz - %d KHz @ %d KHz), " + printk(KERN_INFO " (%d KHz - %d KHz @ %d KHz), " "(N/A, %d mBm)\n", freq_range->start_freq_khz, freq_range->end_freq_khz, diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 96df34c..12dfa62 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -88,7 +88,7 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); request->aborted = aborted; - schedule_work(&wiphy_to_dev(request->wiphy)->scan_done_wk); + queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk); } EXPORT_SYMBOL(cfg80211_scan_done); diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 0115d07..2333d78 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -488,7 +488,7 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, spin_lock_irqsave(&wdev->event_lock, flags); list_add_tail(&ev->list, &wdev->event_list); spin_unlock_irqrestore(&wdev->event_lock, flags); - schedule_work(&rdev->event_work); + queue_work(cfg80211_wq, &rdev->event_work); } EXPORT_SYMBOL(cfg80211_connect_result); @@ -583,7 +583,7 @@ void cfg80211_roamed(struct net_device *dev, const u8 *bssid, spin_lock_irqsave(&wdev->event_lock, flags); list_add_tail(&ev->list, &wdev->event_list); spin_unlock_irqrestore(&wdev->event_lock, flags); - schedule_work(&rdev->event_work); + queue_work(cfg80211_wq, &rdev->event_work); } EXPORT_SYMBOL(cfg80211_roamed); @@ -681,7 +681,7 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason, spin_lock_irqsave(&wdev->event_lock, flags); list_add_tail(&ev->list, &wdev->event_list); spin_unlock_irqrestore(&wdev->event_lock, flags); - schedule_work(&rdev->event_work); + queue_work(cfg80211_wq, &rdev->event_work); } EXPORT_SYMBOL(cfg80211_disconnected); diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 29091ac..584eb48 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -1401,6 +1401,47 @@ int cfg80211_wext_giwessid(struct net_device *dev, } EXPORT_SYMBOL_GPL(cfg80211_wext_giwessid); +int cfg80211_wext_siwpmksa(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + struct cfg80211_pmksa cfg_pmksa; + struct iw_pmksa *pmksa = (struct iw_pmksa *)extra; + + memset(&cfg_pmksa, 0, sizeof(struct cfg80211_pmksa)); + + if (wdev->iftype != NL80211_IFTYPE_STATION) + return -EINVAL; + + cfg_pmksa.bssid = pmksa->bssid.sa_data; + cfg_pmksa.pmkid = pmksa->pmkid; + + switch (pmksa->cmd) { + case IW_PMKSA_ADD: + if (!rdev->ops->set_pmksa) + return -EOPNOTSUPP; + + return rdev->ops->set_pmksa(&rdev->wiphy, dev, &cfg_pmksa); + + case IW_PMKSA_REMOVE: + if (!rdev->ops->del_pmksa) + return -EOPNOTSUPP; + + return rdev->ops->del_pmksa(&rdev->wiphy, dev, &cfg_pmksa); + + case IW_PMKSA_FLUSH: + if (!rdev->ops->flush_pmksa) + return -EOPNOTSUPP; + + return rdev->ops->flush_pmksa(&rdev->wiphy, dev); + + default: + return -EOPNOTSUPP; + } +} + static const iw_handler cfg80211_handlers[] = { [IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname, [IW_IOCTL_IDX(SIOCSIWFREQ)] = (iw_handler) cfg80211_wext_siwfreq, @@ -1433,6 +1474,7 @@ static const iw_handler cfg80211_handlers[] = { [IW_IOCTL_IDX(SIOCSIWAUTH)] = (iw_handler) cfg80211_wext_siwauth, [IW_IOCTL_IDX(SIOCGIWAUTH)] = (iw_handler) cfg80211_wext_giwauth, [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext, + [IW_IOCTL_IDX(SIOCSIWPMKSA)] = (iw_handler) cfg80211_wext_siwpmksa, }; const struct iw_handler_def cfg80211_wext_handler = { diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index 58dfb95..5e1656b 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c @@ -802,7 +802,8 @@ static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd, } /* Generate an event to notify listeners of the change */ - if ((descr->flags & IW_DESCR_FLAG_EVENT) && err == -EIWCOMMIT) { + if ((descr->flags & IW_DESCR_FLAG_EVENT) && + ((err == 0) || (err == -EIWCOMMIT))) { union iwreq_data *data = (union iwreq_data *) iwp; if (descr->flags & IW_DESCR_FLAG_RESTRICT) |