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': EAPLOG(LOG_ERR, "usage: wireless [ -i <interface> ] ( -d | -k | -x <ssid> | -s [ -a ])\n"); exit(0); break; case 'x': /* join network */ network = optarg; break; case 'k': /* set the wireless key */ key_str = optarg; break; case 'd': disassociate = TRUE; break; case 'i': /* specify the interface */ 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 { EAPLOG(LOG_ERR, "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) { EAPLOG(LOG_ERR, "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) { EAPLOG(LOG_ERR, "wireless_set_key failed\n"); } break; default: EAPLOG(LOG_ERR, "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); EAPLOG(LOG_ERR, "attempting to join network '%s'\n", network); if (wireless_join(wref, ssid_str) == FALSE) { EAPLOG(LOG_ERR, "wireless_join failed\n"); } } done: wireless_free(wref); exit(0); return (0); }
/* Retrieve the wifi SAR limits data from VPD and decode it For VPD: key,value pair is in this format "wifi_sar"=[<WRDD><EWRD>][WGDS] WIFI SAR data in CBFS file is expected in same format: [<WRDD><EWRD>][WGDS] [<WRDD><EWRD>] = NUM_SAR_LIMITS * BYTES_PER_SAR_LIMIT bytes. [WGDS]=[WGDS_VERSION][WGDS_DATA] For [WGDS_VERSION] 0x00, [WGDS_DATA] = [GROUP#0][GROUP#1][GROUP#2] [GROUP#<i>] = [2.4Ghz – Max Allowed][2.4Ghz – Chain A Offset] [2.4Ghz – Chain B Offset][5Ghz – Max Allowed] [5Ghz – Chain A Offset][5Ghz – Chain B Offset] [GROUP#0] is for FCC [GROUP#1] is for Europe/Japan [GROUP#2] is for ROW */ int get_wifi_sar_limits(struct wifi_sar_limits *sar_limits) { const char *wifi_sar_limit_key = CROS_VPD_WIFI_SAR_NAME; /* vpd_gets() reads in one less than size characters from the VPD * with a terminating null byte ('\0') stored as the last character into * the buffer, thus the increasing by 1 for buffer_size. */ const size_t buffer_size = (sizeof(struct wifi_sar_limits) / sizeof(uint8_t)) * 2 + 1; char wifi_sar_limit_str[buffer_size]; uint8_t bin_buffer[sizeof(struct wifi_sar_limits)]; size_t sar_cbfs_len, sar_expected_len, bin_buff_adjusted_size; /* keep it backward compatible. Some older platform are shipping without GEO SAR and so older wifi_sar VPD key */ sar_expected_len = buffer_size; bin_buff_adjusted_size = sizeof(struct wifi_sar_limits); if (!IS_ENABLED(CONFIG_GEO_SAR_ENABLE)) { sar_expected_len = buffer_size - sizeof(struct wifi_sar_delta_table) * sizeof(uint8_t) * 2; bin_buff_adjusted_size = sizeof(struct wifi_sar_limits) - sizeof(struct wifi_sar_delta_table); } /* Try to read the SAR limit entry from VPD */ if (!vpd_gets(wifi_sar_limit_key, wifi_sar_limit_str, buffer_size, VPD_ANY)) { printk(BIOS_ERR, "Error: Could not locate '%s' in VPD.\n", wifi_sar_limit_key); if (!IS_ENABLED(CONFIG_WIFI_SAR_CBFS)) return -1; printk(BIOS_DEBUG, "Checking CBFS for default SAR values\n"); sar_cbfs_len = load_sar_file_from_cbfs( (void *) wifi_sar_limit_str, sar_expected_len); if (sar_cbfs_len != sar_expected_len) { printk(BIOS_ERR, "%s has bad len in CBFS\n", WIFI_SAR_CBFS_FILENAME); return -1; } } else { /* VPD key "wifi_sar" found. strlen is checked with addition of * 1 as we have created buffer size 1 char larger for the reason * mentioned at start of this function itself */ if (strlen(wifi_sar_limit_str) + 1 != sar_expected_len) { printk(BIOS_ERR, "WIFI SAR key has bad len in VPD\n"); return -1; } } /* Decode the heximal encoded string to binary values */ if (hexstrtobin(wifi_sar_limit_str, bin_buffer, bin_buff_adjusted_size) < bin_buff_adjusted_size) { printk(BIOS_ERR, "Error: wifi_sar contains non-hex value!\n"); return -1; } memset(sar_limits, 0, sizeof(*sar_limits)); memcpy(sar_limits, bin_buffer, bin_buff_adjusted_size); return 0; }