mlme.c 4.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * cfg80211 MLME SAP interface
 *
 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/nl80211.h>
#include <net/cfg80211.h>
#include "core.h"
#include "nl80211.h"

15
void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp)
16 17 18
{
	struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
19

20
	nl80211_send_rx_auth(rdev, dev, buf, len, gfp);
21
	cfg80211_sme_rx_auth(dev, buf, len);
22 23 24
}
EXPORT_SYMBOL(cfg80211_send_rx_auth);

25
void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp)
26
{
27 28 29
	u16 status_code;
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct wiphy *wiphy = wdev->wiphy;
30
	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
31 32 33 34 35 36
	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
	u8 *ie = mgmt->u.assoc_resp.variable;
	int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);

	status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);

37
	nl80211_send_rx_assoc(rdev, dev, buf, len, gfp);
38 39 40

	cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
				status_code, gfp);
41 42 43
}
EXPORT_SYMBOL(cfg80211_send_rx_assoc);

44
void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp)
45
{
46 47
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct wiphy *wiphy = wdev->wiphy;
48
	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
49 50
	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;

51
	nl80211_send_deauth(rdev, dev, buf, len, gfp);
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67

	if (wdev->sme_state == CFG80211_SME_CONNECTED) {
		u16 reason_code;
		bool from_ap;

		reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);

		from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0;
		__cfg80211_disconnected(dev, gfp, NULL, 0,
					reason_code, from_ap);

		wdev->sme_state = CFG80211_SME_IDLE;
	} else if (wdev->sme_state == CFG80211_SME_CONNECTING) {
		cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
					WLAN_STATUS_UNSPECIFIED_FAILURE, gfp);
	}
68
}
69
EXPORT_SYMBOL(cfg80211_send_deauth);
70

71
void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp)
72
{
73 74
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct wiphy *wiphy = wdev->wiphy;
75
	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
76 77
	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;

78
	nl80211_send_disassoc(rdev, dev, buf, len, gfp);
79

80 81 82 83 84 85 86 87 88 89 90 91
	if (wdev->sme_state == CFG80211_SME_CONNECTED) {
		u16 reason_code;
		bool from_ap;

		reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);

		from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0;
		__cfg80211_disconnected(dev, gfp, NULL, 0,
					reason_code, from_ap);

		wdev->sme_state = CFG80211_SME_IDLE;
	}
92
}
93
EXPORT_SYMBOL(cfg80211_send_disassoc);
94

95
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr, gfp_t gfp)
96
{
97 98
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct wiphy *wiphy = wdev->wiphy;
99
	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
100
	nl80211_send_auth_timeout(rdev, dev, addr, gfp);
101 102 103 104
	if (wdev->sme_state == CFG80211_SME_CONNECTING)
		cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
					WLAN_STATUS_UNSPECIFIED_FAILURE, gfp);
	wdev->sme_state = CFG80211_SME_IDLE;
105 106 107
}
EXPORT_SYMBOL(cfg80211_send_auth_timeout);

108
void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr, gfp_t gfp)
109
{
110 111
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct wiphy *wiphy = wdev->wiphy;
112
	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
113
	nl80211_send_assoc_timeout(rdev, dev, addr, gfp);
114 115 116 117
	if (wdev->sme_state == CFG80211_SME_CONNECTING)
		cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
					WLAN_STATUS_UNSPECIFIED_FAILURE, gfp);
	wdev->sme_state = CFG80211_SME_IDLE;
118 119 120
}
EXPORT_SYMBOL(cfg80211_send_assoc_timeout);

121 122
void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
				  enum nl80211_key_type key_type, int key_id,
123
				  const u8 *tsc, gfp_t gfp)
124 125 126
{
	struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
127 128
#ifdef CONFIG_WIRELESS_EXT
	union iwreq_data wrqu;
129
	char *buf = kmalloc(128, gfp);
130 131 132 133 134 135 136 137 138 139 140 141 142

	if (buf) {
		sprintf(buf, "MLME-MICHAELMICFAILURE.indication("
			"keyid=%d %scast addr=%pM)", key_id,
			key_type == NL80211_KEYTYPE_GROUP ? "broad" : "uni",
			addr);
		memset(&wrqu, 0, sizeof(wrqu));
		wrqu.data.length = strlen(buf);
		wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
		kfree(buf);
	}
#endif

143
	nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc, gfp);
144 145
}
EXPORT_SYMBOL(cfg80211_michael_mic_failure);