#include <TargetConditionals.h>
#ifndef TEST_WIRELESS
#if ! TARGET_OS_EMBEDDED
#include "my_darwin.h"
#endif
#endif TEST_WIRELESS
#include <SystemConfiguration/SCValidation.h>
#ifndef NO_WIRELESS
#include <Apple80211/Apple80211API.h>
#include <Apple80211/Apple80211IE.h>
#include <CoreFoundation/CFString.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <net/ethernet.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <Kernel/IOKit/apple80211/apple80211_ioctl.h>
#include "myCFUtil.h"
#include "wireless.h"
struct scanCallbackEntry_s;
typedef struct scanCallbackEntry_s scanCallbackEntry, * scanCallbackEntryRef;
typedef TAILQ_HEAD(scanCallbackHead_s, scanCallbackEntry_s) scanCallbackHead;
#if 0
static __inline
not_used() {};
#endif 0
typedef struct scanCallbackHead_s * scanCallbackHeadRef;
static scanCallbackHead S_head = TAILQ_HEAD_INITIALIZER(S_head);
static scanCallbackHeadRef S_scanCallbackHead_p = &S_head;
enum {
kScanCallbackStateNone = 0,
kScanCallbackStateStarted = 1,
kScanCallbackStateComplete = 2
};
struct scanCallbackEntry_s {
Apple80211Ref wref;
wireless_scan_callback_t func;
void * arg;
CFStringRef ssid;
uint32_t state;
TAILQ_ENTRY(scanCallbackEntry_s) link;
};
boolean_t
wireless_bind(const char * if_name, wireless_t * wref_p)
{
Apple80211Err error;
boolean_t found = FALSE;
CFStringRef if_name_cf;
Apple80211Ref wref;
error = Apple80211Open(&wref);
if (error != kA11NoErr) {
fprintf(stderr, "Apple80211Open failed, %x\n", error);
return (FALSE);
}
if_name_cf = CFStringCreateWithCString(NULL, if_name,
kCFStringEncodingASCII);
error = Apple80211BindToInterface(wref, if_name_cf);
CFRelease(if_name_cf);
if (error == kA11NoErr) {
*wref_p = (wireless_t)wref;
found = TRUE;
}
else {
#ifdef TEST_WIRELESS
fprintf(stderr, "Apple80211BindToInterface %s failed, %x\n",
if_name, error);
#endif
Apple80211Close(wref);
*wref_p = NULL;
}
return (found);
}
#if TARGET_OS_EMBEDDED
static __inline__ boolean_t
get_ap_address(Apple80211Ref wref, struct ether_addr * AP_mac)
{
CFMutableStringRef ea_str_cf;
boolean_t ret = FALSE;
ea_str_cf = CFStringCreateMutable(NULL, 0);
if (Apple80211Get(wref, APPLE80211_IOC_BSSID, 0, ea_str_cf, 0)
== kA11NoErr) {
char * ea_str;
ea_str = my_CFStringToCString(ea_str_cf, kCFStringEncodingASCII);
if (ea_str != NULL) {
struct ether_addr * ret_ea = ether_aton(ea_str);
if (ret_ea != NULL) {
*AP_mac = *ret_ea;
ret = TRUE;
}
free(ea_str);
}
}
CFRelease(ea_str_cf);
return (ret);
}
#endif
boolean_t
wireless_ap_mac(wireless_t wref, struct ether_addr * AP_mac)
{
const struct ether_addr no_ap = { {0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } };
#if TARGET_OS_EMBEDDED
if (get_ap_address((Apple80211Ref)wref, AP_mac) == FALSE) {
return (FALSE);
}
#else
if (Apple80211Get((Apple80211Ref)wref, APPLE80211_IOC_BSSID, 0,
AP_mac, sizeof(*AP_mac)) != kA11NoErr) {
return (FALSE);
}
#endif
if (memcmp(AP_mac, &no_ap, sizeof(no_ap)) == 0) {
return (FALSE);
}
return (TRUE);
}
boolean_t
wireless_set_key(wireless_t wref, wirelessKeyType type,
int index, const uint8_t * key, int key_length)
{
struct apple80211_key akey;
bzero(&akey, sizeof(akey));
akey.version = APPLE80211_VERSION;
switch (type) {
case kKeyTypeIndexedTx:
akey.key_flags = (APPLE80211_KEY_FLAG_TX
| APPLE80211_KEY_FLAG_UNICAST);
break;
case kKeyTypeIndexedRx:
akey.key_flags = (APPLE80211_KEY_FLAG_RX
| APPLE80211_KEY_FLAG_UNICAST);
break;
case kKeyTypeMulticast:
akey.key_flags = APPLE80211_KEY_FLAG_MULTICAST;
break;
case kKeyTypeDefault:
akey.key_flags = APPLE80211_KEY_FLAG_UNICAST;
break;
default:
return (FALSE);
}
switch (key_length) {
case 5:
akey.key_cipher_type = APPLE80211_CIPHER_WEP_40;
break;
case 13:
akey.key_cipher_type = APPLE80211_CIPHER_WEP_104;
break;
default:
return (FALSE);
}
memcpy(akey.key, key, key_length);
akey.key_len = (uint32_t)key_length;
akey.key_index = (uint16_t)index;
return (Apple80211Set((Apple80211Ref)wref, APPLE80211_IOC_CIPHER_KEY, 0,
&akey, sizeof(akey)) == kA11NoErr);
}
boolean_t
wireless_is_wpa_enterprise(wireless_t wref)
{
Apple80211Err error;
CFDictionaryRef info = NULL;
boolean_t is_wpa_enterprise = FALSE;
CFNumberRef upper_cf;
uint32_t upper;
error = Apple80211CopyValue((Apple80211Ref)wref, APPLE80211_IOC_AUTH_TYPE,
NULL, &info);
if (error != kA11NoErr) {
fprintf(stderr,
"Apple80211CopyValue(APPLE80211_IOC_AUTH_TYPE) failed, 0x%x\n",
error);
goto done;
}
if (info == NULL) {
goto done;
}
upper_cf = CFDictionaryGetValue(info, APPLE80211KEY_AUTH_UPPER);
if (upper_cf == NULL) {
goto done;
}
if (CFNumberGetValue(upper_cf, kCFNumberSInt32Type, &upper) == FALSE) {
goto done;
}
switch (upper) {
case APPLE80211_AUTHTYPE_WPA:
case APPLE80211_AUTHTYPE_WPA2:
is_wpa_enterprise = TRUE;
break;
default:
break;
}
done:
my_CFRelease(&info);
return (is_wpa_enterprise);
}
boolean_t
wireless_set_wpa_pmk(wireless_t wref,
const struct ether_addr * bssid,
const uint8_t * key, int key_length)
{
struct apple80211_key akey;
if (key_length > 32 || key_length < 0) {
return (FALSE);
}
bzero(&akey, sizeof(akey));
akey.version = APPLE80211_VERSION;
if (key_length != 0) {
memcpy(akey.key, key, key_length);
key_length = 32;
}
akey.key_len = (u_int32_t)key_length;
if (bssid != NULL) {
akey.key_cipher_type = APPLE80211_CIPHER_PMKSA;
akey.key_ea = *bssid;
}
else {
akey.key_cipher_type = APPLE80211_CIPHER_PMK;
}
return (Apple80211Set((Apple80211Ref)wref, APPLE80211_IOC_CIPHER_KEY, 0,
&akey, sizeof(akey)) == kA11NoErr);
}
void
wireless_free(wireless_t wref)
{
wireless_scan_cancel(wref);
Apple80211Close((Apple80211Ref)wref);
return;
}
static CFDataRef
wireless_copy_ssid_data(wireless_t wref)
{
CFMutableDataRef ssid;
ssid = CFDataCreateMutable(kCFAllocatorDefault, 0);
if (Apple80211Get((Apple80211Ref)wref, APPLE80211_IOC_SSID, 0,
ssid, 0) != kA11NoErr) {
CFRelease(ssid);
return (NULL);
}
return ((CFDataRef)ssid);
}
static CFStringRef
ssid_string_from_data(CFDataRef data)
{
CFStringRef ssid_str;
ssid_str = CFStringCreateWithBytes(NULL,
CFDataGetBytePtr(data),
CFDataGetLength(data),
kCFStringEncodingUTF8,
FALSE);
if (ssid_str == NULL) {
ssid_str = CFStringCreateWithBytes(NULL,
CFDataGetBytePtr(data),
CFDataGetLength(data),
kCFStringEncodingMacRoman,
FALSE);
}
return (ssid_str);
}
CFStringRef
wireless_copy_ssid_string(wireless_t wref)
{
CFDataRef ssid;
CFStringRef ssid_str;
ssid = wireless_copy_ssid_data(wref);
if (ssid == NULL) {
return (NULL);
}
ssid_str = ssid_string_from_data(ssid);
CFRelease(ssid);
return (ssid_str);
}
static CFDataRef
bssid_string_to_data(CFStringRef bssid)
{
struct ether_addr * eaddr;
char val[32];
if (CFStringGetCString(bssid, val, sizeof(val), kCFStringEncodingASCII)
== FALSE) {
return (NULL);
}
eaddr = ether_aton(val);
if (eaddr == NULL) {
return (NULL);
}
return (CFDataCreate(NULL, (const UInt8 *)eaddr, sizeof(*eaddr)));
}
static CFArrayRef
copy_bssid_list_from_scan(CFArrayRef scan_result, CFStringRef ssid)
{
CFMutableArrayRef bssid_list = NULL;
int count;
int i;
CFRange range;
count = CFArrayGetCount(scan_result);
if (count == 0) {
goto failed;
}
bssid_list = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
range.location = 0;
range.length = 0;
for (i = 0; i < count; i++) {
CFStringRef bssid;
CFDataRef bssid_data;
CFDictionaryRef dict = CFArrayGetValueAtIndex(scan_result, i);
CFStringRef this_ssid;
this_ssid = CFDictionaryGetValue(dict, APPLE80211KEY_SSID_STR);
if (this_ssid == NULL || !CFEqual(this_ssid, ssid)) {
continue;
}
bssid = CFDictionaryGetValue(dict, APPLE80211KEY_BSSID);
if (isA_CFString(bssid) == NULL) {
continue;
}
bssid_data = bssid_string_to_data(bssid);
if (bssid_data != NULL) {
if (!CFArrayContainsValue(bssid_list, range, bssid_data)) {
CFArrayAppendValue(bssid_list, bssid_data);
range.length++;
}
CFRelease(bssid_data);
}
}
if (CFArrayGetCount(bssid_list) == 0) {
CFRelease(bssid_list);
bssid_list = NULL;
}
failed:
return (bssid_list);
}
CFDictionaryRef
make_scan_args(CFStringRef ssid, int num_scans)
{
uint32_t n;
CFMutableDictionaryRef scan_args;
CFNumberRef val;
scan_args = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(scan_args, APPLE80211KEY_SCAN_SSID, ssid);
CFDictionarySetValue(scan_args, APPLE80211KEY_SCAN_MERGE,
kCFBooleanFalse);
n = num_scans;
val = CFNumberCreate(NULL, kCFNumberSInt32Type, &n);
CFDictionarySetValue(scan_args, APPLE80211KEY_SCAN_NUM_SCANS, val);
CFRelease(val);
n = APPLE80211_MODE_AUTO;
val = CFNumberCreate(NULL, kCFNumberSInt32Type, &n);
CFDictionarySetValue(scan_args, APPLE80211KEY_SCAN_PHY_MODE, val);
CFRelease(val);
n = APPLE80211_SCAN_TYPE_ACTIVE;
val = CFNumberCreate(NULL, kCFNumberSInt32Type, &n);
CFDictionarySetValue(scan_args, APPLE80211KEY_SCAN_TYPE, val);
CFRelease(val);
return (scan_args);
}
static scanCallbackEntryRef
scanCallbackEntryFind(Apple80211Ref wref)
{
scanCallbackEntryRef scan;
TAILQ_FOREACH(scan, S_scanCallbackHead_p, link) {
if (scan->wref == wref) {
return (scan);
}
}
return (NULL);
}
#ifdef APPLE80211KEY_SCAN_BSSID_LIST
static void
scanCallbackEvent(Apple80211Err err, Apple80211Ref wref,
UInt32 event, void * eventData, UInt32 eventDataLen,
void * context)
#else
static void
scanCallbackEvent(Apple80211Err err, Apple80211Ref wref,
UInt8 event, void * eventData, void * context)
#endif
{
void * arg;
CFArrayRef bssid_list;
scanCallbackEntryRef callback;
wireless_scan_callback_t func;
switch (event) {
case APPLE80211_M_SCAN_DONE:
callback = scanCallbackEntryFind(wref);
if (callback == NULL) {
fprintf(stderr, "%s: no callback?\n",
__FUNCTION__);
break;
}
func = callback->func;
arg = callback->arg;
callback->state = kScanCallbackStateComplete;
bssid_list = copy_bssid_list_from_scan(eventData, callback->ssid);
(*func)((wireless_t)wref, bssid_list, arg);
if (bssid_list != NULL) {
CFRelease(bssid_list);
}
break;
default:
fprintf(stderr, "%s: unexpected event %d",
__FUNCTION__, (int)event);
break;
}
return;
}
void
wireless_scan_cancel(wireless_t this_wref)
{
scanCallbackEntryRef callback;
Apple80211Ref wref = (Apple80211Ref)this_wref;
callback = scanCallbackEntryFind(wref);
if (callback == NULL) {
return;
}
TAILQ_REMOVE(S_scanCallbackHead_p, callback, link);
(void)Apple80211EventMonitoringHalt(wref);
CFRelease(callback->ssid);
free(callback);
return;
}
boolean_t
wireless_scan(wireless_t this_wref, CFStringRef ssid, int num_scans,
wireless_scan_callback_t func, void * arg)
{
scanCallbackEntryRef callback;
Apple80211Err error;
bool ret = TRUE;
CFDictionaryRef scan_args;
Apple80211Ref wref = (Apple80211Ref)this_wref;
if (ssid == NULL || func == NULL) {
fprintf(stderr, "%s: ssid and/or func NULL\n",
__FUNCTION__);
return (FALSE);
}
callback = scanCallbackEntryFind(wref);
if (callback == NULL) {
#ifdef APPLE80211KEY_SCAN_BSSID_LIST
error = Apple80211EventMonitoringInit(wref, scanCallbackEvent,
NULL, CFRunLoopGetCurrent());
#else
error = Apple80211EventMonitoringInit(wref, scanCallbackEvent,
NULL);
#endif
if (error != kA11NoErr) {
fprintf(stderr,
"%s: Apple80211EventMonitoringInit failed, %d\n",
__FUNCTION__,
error);
ret = FALSE;
goto done;
}
error = Apple80211StartMonitoringEvent(wref, APPLE80211_M_SCAN_DONE);
if (error != kA11NoErr) {
(void)Apple80211EventMonitoringHalt(wref);
fprintf(stderr,
"%s: Apple80211StartMonitoringEvent failed, %d\n",
__FUNCTION__,
error);
ret = FALSE;
goto done;
}
callback = (scanCallbackEntryRef)malloc(sizeof(*callback));
bzero(callback, sizeof(*callback));
callback->wref = wref;
callback->ssid = CFRetain(ssid);
TAILQ_INSERT_TAIL(S_scanCallbackHead_p, callback, link);
}
else if (!CFEqual(callback->ssid, ssid)) {
CFRetain(ssid);
CFRelease(callback->ssid);
callback->ssid = ssid;
callback->state = kScanCallbackStateNone;
}
callback->func = func;
callback->arg = arg;
if (callback->state == kScanCallbackStateStarted) {
fprintf(stderr,
"%s: scan already in progress\n",
__FUNCTION__);
goto done;
}
scan_args = make_scan_args(ssid, num_scans);
error = Apple80211ScanAsync((Apple80211Ref)wref, scan_args);
CFRelease(scan_args);
if (error != kA11NoErr) {
fprintf(stderr,
"%s: Apple80211ScanAsync failed, %d\n",
__FUNCTION__, error);
goto done;
}
callback->state = kScanCallbackStateStarted;
done:
return (ret);
}
#ifdef TEST_WIRELESS
#include <EAP8021X/LinkAddresses.h>
static CFArrayRef
wireless_scan_ssid(wireless_t wref, CFStringRef ssid)
{
CFArrayRef bssid_list = NULL;
Apple80211Err error;
CFDictionaryRef scan_args;
CFArrayRef scan_result = NULL;
scan_args = make_scan_args(ssid, 1);
error = Apple80211Scan((Apple80211Ref)wref, &scan_result, scan_args);
CFRelease(scan_args);
if (error != kA11NoErr) {
fprintf(stderr, "Apple80211Scan failed, %d\n", error);
goto failed;
}
bssid_list = copy_bssid_list_from_scan(scan_result, ssid);
if (bssid_list == NULL) {
fprintf(stderr, "No scan results\n");
}
else {
CFShow(bssid_list);
}
fflush(stdout);
fflush(stderr);
failed:
my_CFRelease(&scan_result);
return (bssid_list);
}
static bool
wireless_async_scan_ssid(wireless_t this_wref, CFStringRef ssid);
static void
async_scan_callback(wireless_t wref, CFArrayRef bssid_list, void * arg)
{
if (bssid_list == NULL) {
fprintf(stderr, "No scan results\n");
}
else {
CFShow(bssid_list);
}
return;
}
static bool
wireless_async_scan_ssid(wireless_t this_wref, CFStringRef ssid)
{
return (wireless_scan(this_wref, ssid, 1, async_scan_callback, (void *)ssid));
}
void
wireless_disassociate(wireless_t wref)
{
#if TARGET_OS_EMBEDDED
Apple80211Set((Apple80211Ref)wref, APPLE80211_IOC_DISASSOCIATE, 0, 0, 0);
#else
Apple80211Err error;
error = Apple80211Disassociate( (Apple80211Ref)wref );
if (error != kA11NoErr) {
fprintf(stderr,
"wireless_disassociate: WirelessDisassociate failed, %x\n",
error);
}
#endif
return;
}
static char *
wireless_first(wireless_t * wref_p)
{
int count;
Apple80211Err error;
int i;
CFArrayRef if_name_list;
char * ret_name = NULL;
Apple80211Ref wref;
error = Apple80211Open(&wref);
if (error != kA11NoErr) {
fprintf(stderr, "Apple80211Open failed, %x\n", error);
return (NULL);
}
error = Apple80211GetIfListCopy(wref, &if_name_list);
if (error != kA11NoErr) {
fprintf(stderr, "Apple80211GetIfListCopy failed, %x\n", error);
goto done;
}
count = CFArrayGetCount(if_name_list);
if (count > 0) {
CFStringRef if_name;
if_name = CFArrayGetValueAtIndex(if_name_list, 0);
error = Apple80211BindToInterface(wref, if_name);
if (error != kA11NoErr) {
fprintf(stderr, "Apple80211BindToInterface failed, %x\n",
error);
}
else {
ret_name = my_CFStringToCString(if_name, kCFStringEncodingASCII);
}
}
CFRelease(if_name_list);
done:
if (ret_name == NULL) {
Apple80211Close(wref);
*wref_p = NULL;
}
else {
*wref_p = (wireless_t)wref;
}
return (ret_name);
}
static boolean_t
wireless_join(wireless_t wref, CFStringRef ssid)
{
Apple80211Err error;
boolean_t ret = FALSE;
CFMutableDictionaryRef scan_args = NULL;
CFArrayRef scan_result = NULL;
scan_args = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks );
CFDictionarySetValue(scan_args, APPLE80211KEY_SCAN_SSID, ssid);
error = Apple80211Scan((Apple80211Ref)wref, &scan_result, scan_args);
CFRelease(scan_args);
if (error != kA11NoErr) {
fprintf(stderr, "Apple80211Scan failed, %d\n", error);
return (FALSE);
}
if (CFArrayGetCount(scan_result) > 0) {
CFDictionaryRef scan_dict;
scan_dict = CFArrayGetValueAtIndex(scan_result, 0);
error = Apple80211Associate((Apple80211Ref)wref, scan_dict, NULL);
if (error != kA11NoErr) {
error = Apple80211Associate((Apple80211Ref)wref,
scan_dict, CFSTR("1234567890"));
}
if (error == kA11NoErr) {
ret = TRUE;
}
else {
fprintf(stderr, "Apple80211Associate failed, %d\n", error);
CFShow(scan_dict);
}
}
if (scan_result != NULL) {
CFRelease(scan_result);
}
return (ret);
}
#if 0
#include <sys/sockio.h>
static CFStringRef
wireless_ssid_ioc(const char * if_name)
{
struct apple80211req req;
int s;
uint8_t ssid[APPLE80211_MAX_SSID_LEN];
CFStringRef ssid_str = NULL;
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s == -1) {
return (NULL);
}
bzero(&req, sizeof(req));
req.req_len = APPLE80211_MAX_SSID_LEN;
req.req_data = ssid;
req.req_type = APPLE80211_IOC_SSID;
strlcpy(req.req_if_name, if_name, sizeof(req.req_if_name));
if (ioctl(s, SIOCGA80211, (char *)&req) < 0) {
perror("SIOCGA80211");
goto done;
}
ssid_str = CFStringCreateWithBytes(NULL, ssid, req.req_len,
kCFStringEncodingUTF8,
FALSE);
if (ssid_str == NULL) {
ssid_str = CFStringCreateWithBytes(NULL, ssid, req.req_len,
kCFStringEncodingMacRoman,
FALSE);
}
done:
close(s);
return (ssid_str);
}
#endif 0
static void
hexstrtobin(const char * hexstr, int hexlen, uint8_t * bin, int bin_len)
{
int i;
int j;
char tmp[3];
tmp[2] = '\0';
for (i = 0, j = 0; i < hexlen && j < bin_len; i += 2, j++) {
tmp[0] = hexstr[i];
tmp[1] = hexstr[i + 1];
bin[j] = (uint8_t)strtoul(tmp, NULL, 16);
}
return;
}
static boolean_t
get_mac_address(const char * if_name, struct sockaddr_dl * ret)
{
struct sockaddr_dl * dl_p;
boolean_t found = FALSE;
LinkAddressesRef list;
list = LinkAddresses_create();
if (list != NULL) {
dl_p = LinkAddresses_lookup(list, (char *)if_name);
if (dl_p != NULL) {
*ret = *dl_p;
found = TRUE;
}
LinkAddresses_free(&list);
}
return (found);
}
struct ssid_wref {
CFStringRef ssid;
wireless_t wref;
};
static void
before_blocking(CFRunLoopObserverRef observer,
CFRunLoopActivity activity, void *info)
{
scanCallbackEntryRef callback;
struct ssid_wref * ref = (struct ssid_wref *)info;
callback = scanCallbackEntryFind((Apple80211Ref)ref->wref);
if (callback->state == kScanCallbackStateComplete) {
printf("scan is complete, starting another scan\n");
wireless_scan(ref->wref, ref->ssid, 1, async_scan_callback,
(void *)ref->ssid);
}
else {
printf("before blocking\n");
}
return;
}
int
main(int argc, char * argv[])
{
int a_flag = 0;
struct ether_addr AP_mac;
int ch;
boolean_t disassociate = FALSE;
const char * if_name = NULL;
boolean_t has_wireless;
const char * key_str = NULL;
const char * network = NULL;
int scan_current_ssid = FALSE;
struct sockaddr_dl w;
wireless_t wref;
while ((ch = getopt(argc, argv, "adhHi:k:sx:")) != EOF) {
switch ((char)ch) {
case 'a':
a_flag = 1;
break;
case 'h':
case 'H':
fprintf(stderr,
"usage: wireless [ -i <interface> ] ( -d | -k | -x <ssid> | -s [ -a ])\n");
exit(0);
break;
case 'x':
network = optarg;
break;
case 'k':
key_str = optarg;
break;
case 'd':
disassociate = TRUE;
break;
case 'i':
if_name = optarg;
break;
case 's':
scan_current_ssid = TRUE;
break;
default:
break;
}
}
if (if_name != NULL) {
if (wireless_bind(if_name, &wref) == FALSE) {
printf("interface '%s' is not present or not AirPort\n",
if_name);
exit(1);
}
}
else if ((if_name = wireless_first(&wref)) == NULL) {
printf("no AirPort card\n");
exit(0);
}
get_mac_address(if_name, &w);
printf("AirPort: %s %s\n", if_name,
ether_ntoa((struct ether_addr *)(w.sdl_data + w.sdl_nlen)));
if (wireless_ap_mac(wref, &AP_mac) == FALSE) {
printf("Not associated\n");
}
else {
CFStringRef ssid;
printf("Access Point: %s\n", ether_ntoa(&AP_mac));
ssid = wireless_copy_ssid_string(wref);
if (ssid != NULL) {
printf("SSID: ");
fflush(stdout);
CFShow(ssid);
fflush(stderr);
}
if (wireless_is_wpa_enterprise(wref) == TRUE) {
printf("WPA Enterprise\n");
}
else {
printf("Not WPA Enterprise\n");
}
if (disassociate) {
wireless_disassociate(wref);
goto done;
}
else if (scan_current_ssid) {
if (a_flag) {
if (wireless_async_scan_ssid(wref, ssid)) {
CFRunLoopObserverContext context
= { 0, NULL, NULL, NULL, NULL };
CFRunLoopObserverRef observer;
struct ssid_wref ref;
ref.ssid = ssid;
ref.wref = wref;
context.info = &ref;
observer
= CFRunLoopObserverCreate(NULL,
kCFRunLoopBeforeWaiting,
TRUE, 0, before_blocking,
&context);
if (observer != NULL) {
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer,
kCFRunLoopDefaultMode);
}
else {
fprintf(stderr, "start_initialization: "
"CFRunLoopObserverCreate failed!");
}
CFRunLoopRun();
}
else {
exit(1);
}
}
else {
wireless_scan_ssid(wref, ssid);
}
}
my_CFRelease(&ssid);
}
if (key_str) {
uint8_t key[13];
int key_len;
int hex_len = strlen(key_str);
if (hex_len & 0x1) {
fprintf(stderr, "invalid key, odd number of hex bytes\n");
exit(1);
}
key_len = hex_len / 2;
switch (key_len) {
case 5:
case 13:
hexstrtobin(key_str, hex_len, key, key_len);
if (wireless_set_key(wref, 0, 0, key, key_len)
== FALSE) {
fprintf(stderr, "wireless_set_key failed\n");
}
break;
default:
fprintf(stderr,
"invalid key length %d,"
" must be 5 or 13 hex bytes\n", key_len);
exit(1);
break;
}
}
else if (network != NULL) {
CFDataRef data;
CFStringRef ssid_str;
data = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)network,
strlen(network), kCFAllocatorNull);
ssid_str = ssid_string_from_data(data);
fprintf(stderr, "attempting to join network '%s'\n", network);
if (wireless_join(wref, ssid_str) == FALSE) {
fprintf(stderr, "wireless_join failed\n");
}
}
done:
wireless_free(wref);
exit(0);
return (0);
}
#endif TEST_WIRELESS
#endif NO_WIRELESS