Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
wext_events.c
Go to the documentation of this file.
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  */
44 void
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;
57 
58  if (resp_ie_len == 0) resp_ie = NULL;
59  wrqu.data.length = resp_ie_len;
60  wrqu.data.flags = 0;
62 
63  if (scan_ie_len > 0) {
64  wrqu.data.length = scan_ie_len;
65  wrqu.data.flags = 0;
67  }
68 
69  memcpy(&wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
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  */
95 void
97 {
98 #if WIRELESS_EXT > 17
99  union iwreq_data wrqu;
100 
101  memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
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  */
126 void
128 {
129 #if WIRELESS_EXT > 17
130  union iwreq_data wrqu;
131 
132  wrqu.data.length = 0;
133  wrqu.data.flags = 0;
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
158 static 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
188 static 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=%pM)",
199  key_idx, (key_type == CSR_GROUP) ? "broad" : "uni", macaddr);
200  memset(&wrqu, 0, sizeof(wrqu));
201  wrqu.data.length = strlen(buf);
202  wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
203 }
204 #else /* WIRELESS_EXT >= 15 */
205 static inline void
206 _send_michaelmicfailure_event(struct net_device *dev,
207  int count, const unsigned char *macaddr,
208  int key_type, int key_idx,
209  unsigned char *tsc)
210 {
211  /* Not supported before WEXT 15 */
212 }
213 #endif /* WIRELESS_EXT >= 15 */
214 
215 
216 void
218  u16 count,
220  CsrWifiSmeKeyType keyType,
221  u16 interfaceTag)
222 {
223  unsigned char tsc[8] = {0};
224 
225  if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) {
226  unifi_error(priv, "wext_send_michaelmicfailure_event bad interfaceTag\n");
227  return;
228  }
229 
230  _send_michaelmicfailure_event(priv->netdev[interfaceTag],
231  count,
232  address.a,
233  keyType,
234  0,
235  tsc);
236 } /* wext_send_michaelmicfailure_event() */
237 
238 void
240 {
241 #if WIRELESS_EXT > 17
242  union iwreq_data wrqu;
243  struct iw_pmkid_cand pmkid_cand;
244 
245  if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) {
246  unifi_error(priv, "wext_send_pmkid_candidate_event bad interfaceTag\n");
247  return;
248  }
249 
250  memset(&pmkid_cand, 0, sizeof(pmkid_cand));
251 
252  if (preauth_allowed) {
253  pmkid_cand.flags |= IW_PMKID_CAND_PREAUTH;
254  }
255  pmkid_cand.bssid.sa_family = ARPHRD_ETHER;
256  memcpy(pmkid_cand.bssid.sa_data, bssid.a, ETH_ALEN);
257  /* Used as priority, smaller the number higher the priority, not really used in our case */
258  pmkid_cand.index = 1;
259 
260  memset(&wrqu, 0, sizeof(wrqu));
261  wrqu.data.length = sizeof(pmkid_cand);
262 
263  wireless_send_event(priv->netdev[interfaceTag], IWEVPMKIDCAND, &wrqu, (char *)&pmkid_cand);
264 #endif
265 } /* wext_send_pmkid_candidate_event() */
266 
267 /*
268  * Send a custom WEXT event to say we have completed initialisation
269  * and are now ready for WEXT ioctls. Used by Android wpa_supplicant.
270  */
271 void
273 {
274 #if WIRELESS_EXT > 17
275  union iwreq_data wrqu;
276  char data[] = "STARTED";
277 
278  wrqu.data.length = sizeof(data);
279  wrqu.data.flags = 0;
281 #endif
282 } /* wext_send_started_event() */
283