2 * WPA Supplicant - iPhone/iPod touch Apple80211 driver interface
3 * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
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.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
16 #define Boolean __DummyBoolean
17 #include <CoreFoundation/CoreFoundation.h>
23 #include "common/ieee802_11_defs.h"
25 #include "MobileApple80211.h"
27 struct wpa_driver_iphone_data {
29 Apple80211Ref wireless_ctx;
30 CFArrayRef scan_results;
35 static const void * cfdict_get_key_str(CFDictionaryRef dict, const char *key)
38 CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, key,
39 kCFStringEncodingMacRoman);
43 res = CFDictionaryGetValue(dict, str);
49 static int wpa_driver_iphone_get_ssid(void *priv, u8 *ssid)
51 struct wpa_driver_iphone_data *drv = priv;
55 err = Apple80211CopyValue(drv->wireless_ctx, APPLE80211_VALUE_SSID, 0,
58 wpa_printf(MSG_DEBUG, "iPhone: Apple80211CopyValue(SSID) "
63 len = CFDataGetLength(data);
68 os_memcpy(ssid, CFDataGetBytePtr(data), len);
75 static int wpa_driver_iphone_get_bssid(void *priv, u8 *bssid)
77 struct wpa_driver_iphone_data *drv = priv;
80 int a1, a2, a3, a4, a5, a6;
82 err = Apple80211CopyValue(drv->wireless_ctx, APPLE80211_VALUE_BSSID, 0,
85 wpa_printf(MSG_DEBUG, "iPhone: Apple80211CopyValue(BSSID) "
90 sscanf(CFStringGetCStringPtr(data, kCFStringEncodingMacRoman),
91 "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6);
105 static void wpa_driver_iphone_scan_timeout(void *eloop_ctx, void *timeout_ctx)
107 wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
111 static int wpa_driver_iphone_scan(void *priv, const u8 *ssid, size_t ssid_len)
113 struct wpa_driver_iphone_data *drv = priv;
116 if (drv->scan_results) {
117 CFRelease(drv->scan_results);
118 drv->scan_results = NULL;
121 err = Apple80211Scan(drv->wireless_ctx, &drv->scan_results, NULL);
123 wpa_printf(MSG_DEBUG, "iPhone: Apple80211Scan failed: %d",
128 eloop_register_timeout(0, 0, wpa_driver_iphone_scan_timeout, drv,
134 static int wpa_driver_iphone_get_scan_results(void *priv,
135 struct wpa_scan_result *results,
138 struct wpa_driver_iphone_data *drv = priv;
141 if (drv->scan_results == NULL)
144 num = CFArrayGetCount(drv->scan_results);
147 os_memset(results, 0, num * sizeof(struct wpa_scan_result));
149 for (i = 0; i < num; i++) {
150 struct wpa_scan_result *res = &results[i];
151 CFDictionaryRef dict =
152 CFArrayGetValueAtIndex(drv->scan_results, i);
158 data = cfdict_get_key_str(dict, "SSID");
160 res->ssid_len = CFDataGetLength(data);
161 if (res->ssid_len > 32)
163 os_memcpy(res->ssid, CFDataGetBytePtr(data),
167 str = cfdict_get_key_str(dict, "BSSID");
169 int a1, a2, a3, a4, a5, a6;
170 sscanf(CFStringGetCStringPtr(
171 str, kCFStringEncodingMacRoman),
173 &a1, &a2, &a3, &a4, &a5, &a6);
182 num = cfdict_get_key_str(dict, "CAPABILITIES");
184 if (CFNumberGetValue(num, kCFNumberSInt32Type, &val))
188 num = cfdict_get_key_str(dict, "CHANNEL");
190 if (CFNumberGetValue(num, kCFNumberSInt32Type, &val))
191 res->freq = 2407 + val * 5;
194 num = cfdict_get_key_str(dict, "RSSI");
196 if (CFNumberGetValue(num, kCFNumberSInt32Type, &val))
200 num = cfdict_get_key_str(dict, "NOISE");
202 if (CFNumberGetValue(num, kCFNumberSInt32Type, &val))
206 data = cfdict_get_key_str(dict, "IE");
208 u8 *ptr = (u8 *) CFDataGetBytePtr(data);
209 int len = CFDataGetLength(data);
210 u8 *pos = ptr, *end = ptr + len;
212 while (pos + 2 < end) {
213 if (pos + 2 + pos[1] > end)
215 if (pos[0] == WLAN_EID_RSN &&
216 pos[1] <= SSID_MAX_WPA_IE_LEN) {
217 os_memcpy(res->rsn_ie, pos,
219 res->rsn_ie_len = 2 + pos[1];
221 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC &&
222 pos[1] > 4 && pos[2] == 0x00 &&
223 pos[3] == 0x50 && pos[4] == 0xf2 &&
225 os_memcpy(res->wpa_ie, pos,
227 res->wpa_ie_len = 2 + pos[1];
230 pos = pos + 2 + pos[1];
239 static void wpa_driver_iphone_assoc_timeout(void *eloop_ctx, void *timeout_ctx)
241 struct wpa_driver_iphone_data *drv = eloop_ctx;
244 if (wpa_driver_iphone_get_bssid(drv, bssid) != 0) {
245 eloop_register_timeout(1, 0, wpa_driver_iphone_assoc_timeout,
250 wpa_supplicant_event(timeout_ctx, EVENT_ASSOC, NULL);
254 static int wpa_driver_iphone_associate(
255 void *priv, struct wpa_driver_associate_params *params)
257 struct wpa_driver_iphone_data *drv = priv;
260 CFDictionaryRef bss = NULL;
263 * TODO: Consider generating parameters instead of just using an entry
264 * from scan results in order to support ap_scan=2.
267 if (drv->scan_results == NULL) {
268 wpa_printf(MSG_DEBUG, "iPhone: No scan results - cannot "
273 num = CFArrayGetCount(drv->scan_results);
275 for (i = 0; i < num; i++) {
276 CFDictionaryRef dict =
277 CFArrayGetValueAtIndex(drv->scan_results, i);
280 data = cfdict_get_key_str(dict, "SSID");
284 ssid_len = CFDataGetLength(data);
285 if (ssid_len != params->ssid_len ||
286 os_memcmp(CFDataGetBytePtr(data), params->ssid, ssid_len)
295 wpa_printf(MSG_DEBUG, "iPhone: Could not find SSID from scan "
296 "results - cannot associate");
300 wpa_printf(MSG_DEBUG, "iPhone: Trying to associate with a BSS found "
301 "from scan results");
303 err = Apple80211Associate(drv->wireless_ctx, bss, NULL);
305 wpa_printf(MSG_DEBUG, "iPhone: Apple80211Associate() failed: "
311 * Driver is actually already associated; report association from an
314 eloop_cancel_timeout(wpa_driver_iphone_assoc_timeout, drv, drv->ctx);
315 eloop_register_timeout(0, 0, wpa_driver_iphone_assoc_timeout, drv,
322 static int wpa_driver_iphone_set_key(void *priv, wpa_alg alg, const u8 *addr,
323 int key_idx, int set_tx, const u8 *seq,
324 size_t seq_len, const u8 *key,
328 * TODO: Need to either support configuring PMK for 4-way handshake or
335 static int wpa_driver_iphone_get_capa(void *priv, struct wpa_driver_capa *capa)
337 os_memset(capa, 0, sizeof(*capa));
339 capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
340 WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
341 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
342 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
343 capa->enc = WPA_DRIVER_CAPA_ENC_WEP40 | WPA_DRIVER_CAPA_ENC_WEP104 |
344 WPA_DRIVER_CAPA_ENC_TKIP | WPA_DRIVER_CAPA_ENC_CCMP;
345 capa->auth = WPA_DRIVER_AUTH_OPEN | WPA_DRIVER_AUTH_SHARED |
346 WPA_DRIVER_AUTH_LEAP;
347 capa->flags = WPA_DRIVER_FLAGS_4WAY_HANDSHAKE;
353 static void * wpa_driver_iphone_init(void *ctx, const char *ifname)
355 struct wpa_driver_iphone_data *drv;
359 CFDictionaryRef dict;
361 drv = os_zalloc(sizeof(*drv));
365 err = Apple80211Open(&drv->wireless_ctx);
367 wpa_printf(MSG_ERROR, "iPhone: Apple80211Open failed: %d",
373 name = CFStringCreateWithCString(kCFAllocatorDefault, ifname,
374 kCFStringEncodingISOLatin1);
376 wpa_printf(MSG_ERROR, "iPhone: ifname -> CFString failed");
377 Apple80211Close(drv->wireless_ctx);
382 err = Apple80211BindToInterface(drv->wireless_ctx, name);
386 wpa_printf(MSG_ERROR, "iPhone: Apple80211BindToInterface "
388 Apple80211Close(drv->wireless_ctx);
393 err = Apple80211GetPower(drv->wireless_ctx, &power);
395 wpa_printf(MSG_DEBUG, "iPhone: Apple80211GetPower failed: %d",
398 wpa_printf(MSG_DEBUG, "iPhone: Power=%d", power);
402 err = Apple80211SetPower(drv->wireless_ctx, 1);
404 wpa_printf(MSG_DEBUG, "iPhone: Apple80211SetPower "
406 Apple80211Close(drv->wireless_ctx);
412 err = Apple80211GetInfoCopy(drv->wireless_ctx, &dict);
417 printf("Apple80211GetInfoCopy: %d\n", err);
424 static void wpa_driver_iphone_deinit(void *priv)
426 struct wpa_driver_iphone_data *drv = priv;
429 eloop_cancel_timeout(wpa_driver_iphone_scan_timeout, drv, drv->ctx);
430 eloop_cancel_timeout(wpa_driver_iphone_assoc_timeout, drv, drv->ctx);
432 if (drv->ctrl_power) {
433 wpa_printf(MSG_DEBUG, "iPhone: Power down the interface");
434 err = Apple80211SetPower(drv->wireless_ctx, 0);
436 wpa_printf(MSG_DEBUG, "iPhone: Apple80211SetPower(0) "
441 err = Apple80211Close(drv->wireless_ctx);
443 wpa_printf(MSG_DEBUG, "iPhone: Apple80211Close failed: %d",
447 if (drv->scan_results)
448 CFRelease(drv->scan_results);
454 const struct wpa_driver_ops wpa_driver_iphone_ops = {
456 .desc = "iPhone/iPod touch Apple80211 driver",
457 .get_ssid = wpa_driver_iphone_get_ssid,
458 .get_bssid = wpa_driver_iphone_get_bssid,
459 .init = wpa_driver_iphone_init,
460 .deinit = wpa_driver_iphone_deinit,
461 .scan = wpa_driver_iphone_scan,
462 .get_scan_results = wpa_driver_iphone_get_scan_results,
463 .associate = wpa_driver_iphone_associate,
464 .set_key = wpa_driver_iphone_set_key,
465 .get_capa = wpa_driver_iphone_get_capa,