• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/wpa_supplicant-0.7.3/src/drivers/
1/*
2 * WPA Supplicant - Mac OS X Apple80211 driver interface
3 * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15#include "includes.h"
16#define Boolean __DummyBoolean
17#include <CoreFoundation/CoreFoundation.h>
18#undef Boolean
19
20#include "common.h"
21#include "driver.h"
22#include "eloop.h"
23#include "common/ieee802_11_defs.h"
24
25#include "Apple80211.h"
26
27struct wpa_driver_osx_data {
28	void *ctx;
29	WirelessRef wireless_ctx;
30	CFArrayRef scan_results;
31};
32
33
34#ifndef CONFIG_NO_STDOUT_DEBUG
35extern int wpa_debug_level;
36
37static void dump_dict_cb(const void *key, const void *value, void *context)
38{
39        if (MSG_DEBUG < wpa_debug_level)
40                return;
41
42	wpa_printf(MSG_DEBUG, "Key:");
43	CFShow(key);
44	wpa_printf(MSG_DEBUG, "Value:");
45	CFShow(value);
46}
47#endif /* CONFIG_NO_STDOUT_DEBUG */
48
49
50static void wpa_driver_osx_dump_dict(CFDictionaryRef dict, const char *title)
51{
52#ifndef CONFIG_NO_STDOUT_DEBUG
53	wpa_printf(MSG_DEBUG, "OSX: Dump dictionary %s - %u entries",
54		   title, (unsigned int) CFDictionaryGetCount(dict));
55	CFDictionaryApplyFunction(dict, dump_dict_cb, NULL);
56#endif /* CONFIG_NO_STDOUT_DEBUG */
57}
58
59
60static int wpa_driver_osx_get_ssid(void *priv, u8 *ssid)
61{
62	struct wpa_driver_osx_data *drv = priv;
63	WirelessError err;
64	WirelessInfo info;
65	int len;
66
67	err = WirelessGetInfo(drv->wireless_ctx, &info);
68	if (err) {
69		wpa_printf(MSG_DEBUG, "OSX: WirelessGetInfo failed: %d",
70			   (int) err);
71		return -1;
72	}
73	if (!info.power) {
74		wpa_printf(MSG_DEBUG, "OSX: Wireless device power off");
75		return -1;
76	}
77
78	for (len = 0; len < 32; len++)
79		if (info.ssid[len] == 0)
80			break;
81
82	os_memcpy(ssid, info.ssid, len);
83	return len;
84}
85
86
87static int wpa_driver_osx_get_bssid(void *priv, u8 *bssid)
88{
89	struct wpa_driver_osx_data *drv = priv;
90	WirelessError err;
91	WirelessInfo info;
92
93	err = WirelessGetInfo(drv->wireless_ctx, &info);
94	if (err) {
95		wpa_printf(MSG_DEBUG, "OSX: WirelessGetInfo failed: %d",
96			   (int) err);
97		return -1;
98	}
99	if (!info.power) {
100		wpa_printf(MSG_DEBUG, "OSX: Wireless device power off");
101		return -1;
102	}
103
104	os_memcpy(bssid, info.bssID, ETH_ALEN);
105	return 0;
106}
107
108
109static void wpa_driver_osx_scan_timeout(void *eloop_ctx, void *timeout_ctx)
110{
111	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
112}
113
114
115static int wpa_driver_osx_scan(void *priv, struct wpa_driver_scan_params *params)
116{
117	struct wpa_driver_osx_data *drv = priv;
118	WirelessError err;
119	const u8 *ssid = params->ssids[0].ssid;
120	size_t ssid_len = params->ssids[0].ssid_len;
121
122	if (drv->scan_results) {
123		CFRelease(drv->scan_results);
124		drv->scan_results = NULL;
125	}
126
127	if (ssid) {
128		CFStringRef data;
129		data = CFStringCreateWithBytes(kCFAllocatorDefault,
130					       ssid, ssid_len,
131					       kCFStringEncodingISOLatin1,
132					       FALSE);
133		if (data == NULL) {
134			wpa_printf(MSG_DEBUG, "CFStringCreateWithBytes "
135				   "failed");
136			return -1;
137		}
138
139		err = WirelessDirectedScan(drv->wireless_ctx,
140					   &drv->scan_results, 0, data);
141		CFRelease(data);
142		if (err) {
143			wpa_printf(MSG_DEBUG, "OSX: WirelessDirectedScan "
144				   "failed: 0x%08x", (unsigned int) err);
145			return -1;
146		}
147	} else {
148		err = WirelessScan(drv->wireless_ctx, &drv->scan_results, 0);
149		if (err) {
150			wpa_printf(MSG_DEBUG, "OSX: WirelessScan failed: "
151				   "0x%08x", (unsigned int) err);
152			return -1;
153		}
154	}
155
156	eloop_register_timeout(0, 0, wpa_driver_osx_scan_timeout, drv,
157			       drv->ctx);
158	return 0;
159}
160
161
162static void wpa_driver_osx_add_scan_entry(struct wpa_scan_results *res,
163					  WirelessNetworkInfo *info)
164{
165	struct wpa_scan_res *result, **tmp;
166	size_t extra_len;
167	u8 *pos;
168
169	extra_len = 2 + info->ssid_len;
170
171	result = os_zalloc(sizeof(*result) + extra_len);
172	if (result == NULL)
173		return;
174	os_memcpy(result->bssid, info->bssid, ETH_ALEN);
175	result->freq = 2407 + info->channel * 5;
176	//result->beacon_int =;
177	result->caps = info->capability;
178	//result->qual = info->signal;
179	result->noise = info->noise;
180
181	pos = (u8 *)(result + 1);
182
183	*pos++ = WLAN_EID_SSID;
184	*pos++ = info->ssid_len;
185	os_memcpy(pos, info->ssid, info->ssid_len);
186	pos += info->ssid_len;
187
188	result->ie_len = pos - (u8 *)(result + 1);
189
190	tmp = os_realloc(res->res,
191			 (res->num + 1) * sizeof(struct wpa_scan_res *));
192	if (tmp == NULL) {
193		os_free(result);
194		return;
195	}
196	tmp[res->num++] = result;
197	res->res = tmp;
198}
199
200
201static struct wpa_scan_results * wpa_driver_osx_get_scan_results(void *priv)
202{
203	struct wpa_driver_osx_data *drv = priv;
204	struct wpa_scan_results *res;
205	size_t i, num;
206
207	if (drv->scan_results == NULL)
208		return 0;
209
210	num = CFArrayGetCount(drv->scan_results);
211
212	res = os_zalloc(sizeof(*res));
213	if (res == NULL)
214		return NULL;
215
216	for (i = 0; i < num; i++)
217		wpa_driver_osx_add_scan_entry(res, (WirelessNetworkInfo *)
218			CFDataGetBytePtr(CFArrayGetValueAtIndex(
219				drv->scan_results, i)));
220
221	return res;
222}
223
224
225static void wpa_driver_osx_assoc_timeout(void *eloop_ctx, void *timeout_ctx)
226{
227	struct wpa_driver_osx_data *drv = eloop_ctx;
228	u8 bssid[ETH_ALEN];
229	CFDictionaryRef ai;
230
231	if (wpa_driver_osx_get_bssid(drv, bssid) != 0) {
232		eloop_register_timeout(1, 0, wpa_driver_osx_assoc_timeout,
233				       drv, drv->ctx);
234		return;
235	}
236
237	ai = WirelessGetAssociationInfo(drv->wireless_ctx);
238	if (ai) {
239		wpa_driver_osx_dump_dict(ai, "WirelessGetAssociationInfo");
240		CFRelease(ai);
241	} else {
242		wpa_printf(MSG_DEBUG, "OSX: Failed to get association info");
243	}
244
245	wpa_supplicant_event(timeout_ctx, EVENT_ASSOC, NULL);
246}
247
248
249static int wpa_driver_osx_associate(void *priv,
250				    struct wpa_driver_associate_params *params)
251{
252	struct wpa_driver_osx_data *drv = priv;
253	WirelessError err;
254	CFDataRef ssid;
255	CFStringRef key;
256	int assoc_type;
257
258	ssid = CFDataCreate(kCFAllocatorDefault, params->ssid,
259			    params->ssid_len);
260	if (ssid == NULL)
261		return -1;
262
263	/* TODO: support for WEP */
264	if (params->key_mgmt_suite == KEY_MGMT_PSK) {
265		if (params->passphrase == NULL)
266			return -1;
267		key = CFStringCreateWithCString(kCFAllocatorDefault,
268						params->passphrase,
269						kCFStringEncodingISOLatin1);
270		if (key == NULL) {
271			CFRelease(ssid);
272			return -1;
273		}
274	} else
275		key = NULL;
276
277	if (params->key_mgmt_suite == KEY_MGMT_NONE)
278		assoc_type = 0;
279	else
280		assoc_type = 4;
281
282	wpa_printf(MSG_DEBUG, "OSX: WirelessAssociate(type=%d key=%p)",
283		   assoc_type, key);
284	err = WirelessAssociate(drv->wireless_ctx, assoc_type, ssid, key);
285	CFRelease(ssid);
286	if (key)
287		CFRelease(key);
288	if (err) {
289		wpa_printf(MSG_DEBUG, "OSX: WirelessAssociate failed: 0x%08x",
290			   (unsigned int) err);
291		return -1;
292	}
293
294	/*
295	 * Driver is actually already associated; report association from an
296	 * eloop callback.
297	 */
298	eloop_cancel_timeout(wpa_driver_osx_assoc_timeout, drv, drv->ctx);
299	eloop_register_timeout(0, 0, wpa_driver_osx_assoc_timeout, drv,
300			       drv->ctx);
301
302	return 0;
303}
304
305
306static int wpa_driver_osx_set_key(const char *ifname, void *priv,
307				  enum wpa_alg alg, const u8 *addr,
308				  int key_idx, int set_tx, const u8 *seq,
309				  size_t seq_len, const u8 *key,
310				  size_t key_len)
311{
312	struct wpa_driver_osx_data *drv = priv;
313	WirelessError err;
314
315	if (alg == WPA_ALG_WEP) {
316		err = WirelessSetKey(drv->wireless_ctx, 1, key_idx, key_len,
317				     key);
318		if (err != 0) {
319			wpa_printf(MSG_DEBUG, "OSX: WirelessSetKey failed: "
320				   "0x%08x", (unsigned int) err);
321			return -1;
322		}
323
324		return 0;
325	}
326
327	if (alg == WPA_ALG_PMK) {
328		err = WirelessSetWPAKey(drv->wireless_ctx, 1, key_len, key);
329		if (err != 0) {
330			wpa_printf(MSG_DEBUG, "OSX: WirelessSetWPAKey failed: "
331				   "0x%08x", (unsigned int) err);
332			return -1;
333		}
334		return 0;
335	}
336
337	wpa_printf(MSG_DEBUG, "OSX: Unsupported set_key alg %d", alg);
338	return -1;
339}
340
341
342static int wpa_driver_osx_get_capa(void *priv, struct wpa_driver_capa *capa)
343{
344	os_memset(capa, 0, sizeof(*capa));
345
346	capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
347		WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
348		WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
349		WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
350	capa->enc = WPA_DRIVER_CAPA_ENC_WEP40 | WPA_DRIVER_CAPA_ENC_WEP104 |
351		WPA_DRIVER_CAPA_ENC_TKIP | WPA_DRIVER_CAPA_ENC_CCMP;
352	capa->auth = WPA_DRIVER_AUTH_OPEN | WPA_DRIVER_AUTH_SHARED |
353		WPA_DRIVER_AUTH_LEAP;
354	capa->flags = WPA_DRIVER_FLAGS_4WAY_HANDSHAKE;
355
356	return 0;
357}
358
359
360static void * wpa_driver_osx_init(void *ctx, const char *ifname)
361{
362	struct wpa_driver_osx_data *drv;
363	WirelessError err;
364	u8 enabled, power;
365
366	if (!WirelessIsAvailable()) {
367		wpa_printf(MSG_ERROR, "OSX: No wireless interface available");
368		return NULL;
369	}
370
371	drv = os_zalloc(sizeof(*drv));
372	if (drv == NULL)
373		return NULL;
374	drv->ctx = ctx;
375	err = WirelessAttach(&drv->wireless_ctx, 0);
376	if (err) {
377		wpa_printf(MSG_ERROR, "OSX: WirelessAttach failed: %d",
378			   (int) err);
379		os_free(drv);
380		return NULL;
381	}
382
383	err = WirelessGetEnabled(drv->wireless_ctx, &enabled);
384	if (err)
385		wpa_printf(MSG_DEBUG, "OSX: WirelessGetEnabled failed: 0x%08x",
386			   (unsigned int) err);
387	err = WirelessGetPower(drv->wireless_ctx, &power);
388	if (err)
389		wpa_printf(MSG_DEBUG, "OSX: WirelessGetPower failed: 0x%08x",
390			   (unsigned int) err);
391
392	wpa_printf(MSG_DEBUG, "OSX: Enabled=%d Power=%d", enabled, power);
393
394	if (!enabled) {
395		err = WirelessSetEnabled(drv->wireless_ctx, 1);
396		if (err) {
397			wpa_printf(MSG_DEBUG, "OSX: WirelessSetEnabled failed:"
398				   " 0x%08x", (unsigned int) err);
399			WirelessDetach(drv->wireless_ctx);
400			os_free(drv);
401			return NULL;
402		}
403	}
404
405	if (!power) {
406		err = WirelessSetPower(drv->wireless_ctx, 1);
407		if (err) {
408			wpa_printf(MSG_DEBUG, "OSX: WirelessSetPower failed: "
409				   "0x%08x", (unsigned int) err);
410			WirelessDetach(drv->wireless_ctx);
411			os_free(drv);
412			return NULL;
413		}
414	}
415
416	return drv;
417}
418
419
420static void wpa_driver_osx_deinit(void *priv)
421{
422	struct wpa_driver_osx_data *drv = priv;
423	WirelessError err;
424
425	eloop_cancel_timeout(wpa_driver_osx_scan_timeout, drv, drv->ctx);
426	eloop_cancel_timeout(wpa_driver_osx_assoc_timeout, drv, drv->ctx);
427
428	err = WirelessSetPower(drv->wireless_ctx, 0);
429	if (err) {
430		wpa_printf(MSG_DEBUG, "OSX: WirelessSetPower(0) failed: "
431			   "0x%08x", (unsigned int) err);
432	}
433
434	err = WirelessDetach(drv->wireless_ctx);
435	if (err) {
436		wpa_printf(MSG_DEBUG, "OSX: WirelessDetach failed: 0x%08x",
437			   (unsigned int) err);
438	}
439
440	if (drv->scan_results)
441		CFRelease(drv->scan_results);
442
443	os_free(drv);
444}
445
446
447const struct wpa_driver_ops wpa_driver_osx_ops = {
448	.name = "osx",
449	.desc = "Mac OS X Apple80211 driver",
450	.get_ssid = wpa_driver_osx_get_ssid,
451	.get_bssid = wpa_driver_osx_get_bssid,
452	.init = wpa_driver_osx_init,
453	.deinit = wpa_driver_osx_deinit,
454	.scan2 = wpa_driver_osx_scan,
455	.get_scan_results2 = wpa_driver_osx_get_scan_results,
456	.associate = wpa_driver_osx_associate,
457	.set_key = wpa_driver_osx_set_key,
458	.get_capa = wpa_driver_osx_get_capa,
459};
460