Root/drivers/staging/csr/wext_events.c

1/*
2 * ---------------------------------------------------------------------------
3 * FILE: wext_events.c
4 *
5 * PURPOSE:
6 * Code to generate iwevents.
7 *
8 * Copyright (C) 2006-2008 by Cambridge Silicon Radio Ltd.
9 *
10 * Refer to LICENSE.txt included with this source code for details on
11 * the license terms.
12 *
13 * ---------------------------------------------------------------------------
14 */
15#include <linux/types.h>
16#include <linux/etherdevice.h>
17#include <linux/if_arp.h>
18#include "csr_wifi_hip_unifi.h"
19#include "unifi_priv.h"
20
21
22
23/*
24 * ---------------------------------------------------------------------------
25 * wext_send_assoc_event
26 *
27 * Send wireless-extension events up to userland to announce
28 * successful association with an AP.
29 *
30 * Arguments:
31 * priv Pointer to driver context.
32 * bssid MAC address of AP we associated with
33 * req_ie, req_ie_len IEs in the original request
34 * resp_ie, resp_ie_len IEs in the response
35 *
36 * Returns:
37 * None.
38 *
39 * Notes:
40 * This is sent on first successful association, and again if we
41 * roam to another AP.
42 * ---------------------------------------------------------------------------
43 */
44void
45wext_send_assoc_event(unifi_priv_t *priv, unsigned char *bssid,
46                      unsigned char *req_ie, int req_ie_len,
47                      unsigned char *resp_ie, int resp_ie_len,
48                      unsigned char *scan_ie, unsigned int scan_ie_len)
49{
50#if WIRELESS_EXT > 17
51    union iwreq_data wrqu;
52
53    if (req_ie_len == 0) req_ie = NULL;
54    wrqu.data.length = req_ie_len;
55    wrqu.data.flags = 0;
56    wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], IWEVASSOCREQIE, &wrqu, req_ie);
57
58    if (resp_ie_len == 0) resp_ie = NULL;
59    wrqu.data.length = resp_ie_len;
60    wrqu.data.flags = 0;
61    wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], IWEVASSOCRESPIE, &wrqu, resp_ie);
62
63    if (scan_ie_len > 0) {
64        wrqu.data.length = scan_ie_len;
65        wrqu.data.flags = 0;
66        wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], IWEVGENIE, &wrqu, scan_ie);
67    }
68
69    memcpy(&wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
70    wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], SIOCGIWAP, &wrqu, NULL);
71#endif
72} /* wext_send_assoc_event() */
73
74
75
76/*
77 * ---------------------------------------------------------------------------
78 * wext_send_disassoc_event
79 *
80 * Send a wireless-extension event up to userland to announce
81 * that we disassociated from an AP.
82 *
83 * Arguments:
84 * priv Pointer to driver context.
85 *
86 * Returns:
87 * None.
88 *
89 * Notes:
90 * The semantics of wpa_supplicant (the userland SME application) are
91 * that a SIOCGIWAP event with MAC address of all zero means
92 * disassociate.
93 * ---------------------------------------------------------------------------
94 */
95void
96wext_send_disassoc_event(unifi_priv_t *priv)
97{
98#if WIRELESS_EXT > 17
99    union iwreq_data wrqu;
100
101    memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
102    wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], SIOCGIWAP, &wrqu, NULL);
103#endif
104} /* wext_send_disassoc_event() */
105
106
107
108/*
109 * ---------------------------------------------------------------------------
110 * wext_send_scan_results_event
111 *
112 * Send wireless-extension events up to userland to announce
113 * completion of a scan.
114 *
115 * Arguments:
116 * priv Pointer to driver context.
117 *
118 * Returns:
119 * None.
120 *
121 * Notes:
122 * This doesn't actually report the results, they are retrieved
123 * using the SIOCGIWSCAN ioctl command.
124 * ---------------------------------------------------------------------------
125 */
126void
127wext_send_scan_results_event(unifi_priv_t *priv)
128{
129#if WIRELESS_EXT > 17
130    union iwreq_data wrqu;
131
132    wrqu.data.length = 0;
133    wrqu.data.flags = 0;
134    wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], SIOCGIWSCAN, &wrqu, NULL);
135
136#endif
137} /* wext_send_scan_results_event() */
138
139
140
141/*
142 * ---------------------------------------------------------------------------
143 * wext_send_michaelmicfailure_event
144 *
145 * Send wireless-extension events up to userland to announce
146 * completion of a scan.
147 *
148 * Arguments:
149 * priv Pointer to driver context.
150 * count, macaddr, key_type, key_idx, tsc
151 * Parameters from report from UniFi.
152 *
153 * Returns:
154 * None.
155 * ---------------------------------------------------------------------------
156 */
157#if WIRELESS_EXT >= 18
158static inline void
159_send_michaelmicfailure_event(struct net_device *dev,
160                              int count, const unsigned char *macaddr,
161                              int key_type, int key_idx,
162                              unsigned char *tsc)
163{
164    union iwreq_data wrqu;
165    struct iw_michaelmicfailure mmf;
166
167    memset(&mmf, 0, sizeof(mmf));
168
169    mmf.flags = key_idx & IW_MICFAILURE_KEY_ID;
170    if (key_type == CSR_GROUP) {
171        mmf.flags |= IW_MICFAILURE_GROUP;
172    } else {
173        mmf.flags |= IW_MICFAILURE_PAIRWISE;
174    }
175    mmf.flags |= ((count << 5) & IW_MICFAILURE_COUNT);
176
177    mmf.src_addr.sa_family = ARPHRD_ETHER;
178    memcpy(mmf.src_addr.sa_data, macaddr, ETH_ALEN);
179
180    memcpy(mmf.tsc, tsc, IW_ENCODE_SEQ_MAX_SIZE);
181
182    memset(&wrqu, 0, sizeof(wrqu));
183    wrqu.data.length = sizeof(mmf);
184
185    wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&mmf);
186}
187#elif WIRELESS_EXT >= 15
188static inline void
189_send_michaelmicfailure_event(struct net_device *dev,
190                              int count, const unsigned char *macaddr,
191                              int key_type, int key_idx,
192                              unsigned char *tsc)
193{
194    union iwreq_data wrqu;
195    char buf[128];
196
197    sprintf(buf,
198            "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr=%02x:%02x:%02x:%02x:%02x:%02x)",
199            key_idx, (key_type == CSR_GROUP) ? "broad" : "uni",
200            macaddr[0], macaddr[1], macaddr[2],
201            macaddr[3], macaddr[4], macaddr[5]);
202    memset(&wrqu, 0, sizeof(wrqu));
203    wrqu.data.length = strlen(buf);
204    wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
205}
206#else /* WIRELESS_EXT >= 15 */
207static inline void
208_send_michaelmicfailure_event(struct net_device *dev,
209                              int count, const unsigned char *macaddr,
210                              int key_type, int key_idx,
211                              unsigned char *tsc)
212{
213    /* Not supported before WEXT 15 */
214}
215#endif /* WIRELESS_EXT >= 15 */
216
217
218void
219wext_send_michaelmicfailure_event(unifi_priv_t *priv,
220                                  u16 count,
221                                  CsrWifiMacAddress address,
222                                  CsrWifiSmeKeyType keyType,
223                                  u16 interfaceTag)
224{
225    unsigned char tsc[8] = {0};
226
227    if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) {
228        unifi_error(priv, "wext_send_michaelmicfailure_event bad interfaceTag\n");
229        return;
230    }
231
232    _send_michaelmicfailure_event(priv->netdev[interfaceTag],
233                                  count,
234                                  address.a,
235                                  keyType,
236                                  0,
237                                  tsc);
238} /* wext_send_michaelmicfailure_event() */
239
240void
241wext_send_pmkid_candidate_event(unifi_priv_t *priv, CsrWifiMacAddress bssid, u8 preauth_allowed, u16 interfaceTag)
242{
243#if WIRELESS_EXT > 17
244    union iwreq_data wrqu;
245    struct iw_pmkid_cand pmkid_cand;
246
247    if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) {
248        unifi_error(priv, "wext_send_pmkid_candidate_event bad interfaceTag\n");
249        return;
250    }
251
252    memset(&pmkid_cand, 0, sizeof(pmkid_cand));
253
254    if (preauth_allowed) {
255        pmkid_cand.flags |= IW_PMKID_CAND_PREAUTH;
256    }
257    pmkid_cand.bssid.sa_family = ARPHRD_ETHER;
258    memcpy(pmkid_cand.bssid.sa_data, bssid.a, ETH_ALEN);
259    /* Used as priority, smaller the number higher the priority, not really used in our case */
260    pmkid_cand.index = 1;
261
262    memset(&wrqu, 0, sizeof(wrqu));
263    wrqu.data.length = sizeof(pmkid_cand);
264
265    wireless_send_event(priv->netdev[interfaceTag], IWEVPMKIDCAND, &wrqu, (char *)&pmkid_cand);
266#endif
267} /* wext_send_pmkid_candidate_event() */
268
269/*
270 * Send a custom WEXT event to say we have completed initialisation
271 * and are now ready for WEXT ioctls. Used by Android wpa_supplicant.
272 */
273void
274wext_send_started_event(unifi_priv_t *priv)
275{
276#if WIRELESS_EXT > 17
277    union iwreq_data wrqu;
278    char data[] = "STARTED";
279
280    wrqu.data.length = sizeof(data);
281    wrqu.data.flags = 0;
282    wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], IWEVCUSTOM, &wrqu, data);
283#endif
284} /* wext_send_started_event() */
285
286

Archive Download this file



interactive