Skip to content

Instantly share code, notes, and snippets.

@an-roo
Created June 7, 2010 00:07
Show Gist options
  • Select an option

  • Save an-roo/428052 to your computer and use it in GitHub Desktop.

Select an option

Save an-roo/428052 to your computer and use it in GitHub Desktop.
wl_iw_setap(struct net_device *dev, struct ap_profile *ap)
{
int updown = 0;
int channel = 0;
int wsec = 0;
int wpa_auth = 0;
int apstate = 1;
wlc_ssid_t ap_ssid;
wlc_ssid_t null_ssid;
int max_assoc = 8;
//char deauth_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
int i;
char * ptr;
int mpc = 0;
int wep = 0;
wl_wsec_key_t key;
#ifdef CUSTOMER_HW2 /* HTC need limited the selected channel */
int start_channel, end_channel;
#endif
memset(&null_ssid, 0, sizeof(wlc_ssid_t));
WL_SOFTAP(("wl_iw: set ap profile:\n"));
WL_SOFTAP((" ssid = %s\n", ap->ssid));
WL_SOFTAP((" security = %s\n", ap->sec));
if (ap->key[0] != '\0')
WL_SOFTAP((" key = %s\n", ap->key));
WL_SOFTAP((" channel = %d\n", ap->channel));
WL_SOFTAP((" max scb = %d\n", ap->max_scb));
dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown));
apstate = 0;
dev_wlc_ioctl(dev, WLC_SET_AP, &apstate, sizeof(apstate));
apstate = 1;
dev_wlc_ioctl(dev, WLC_SET_AP, &apstate, sizeof(apstate));
/* check auto channel later */
#ifdef CUSTOMER_HW2 /* HTC need limited the selected channel */
if ((ap->channel >> 8) || (ap->channel == 0))
#else
if (ap->channel == 0)
#endif
#if 1
{
int chosen = 0;
wl_uint32_list_t request;
int rescan = 0;
int retry = 0;
int ret = 0;
dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown));
dev_wlc_ioctl(dev, WLC_SET_SSID, &null_ssid, sizeof(null_ssid));
auto_channel_retry:
request.count = htod32(0);
ret = dev_wlc_ioctl(dev, WLC_START_CHANNEL_SEL, &request, sizeof(request));
if (ret < 0) {
WL_SOFTAP(("can't start auto channel scan\n"));
return -1;
}
get_channel_retry:
bcm_mdelay(500);
ret = dev_wlc_ioctl(dev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen));
if (ret < 0 || dtoh32(chosen) == 0) {
if (retry++ < 3)
goto get_channel_retry;
else {
WL_SOFTAP(("can't get auto channel sel, err = %d, chosen = %d\n", ret, chosen));
return -1;
}
}
if ((chosen == 1) && (!rescan++))
goto auto_channel_retry;
#ifdef CUSTOMER_HW2 /* HTC need limited the selected channel */
if (ap->channel == 0)
ap->channel = chosen;
else {
start_channel = (ap->channel >> 8) & 0xff;
end_channel = ap->channel & 0xff;
WL_SOFTAP(("channel range from %d to %d\n", start_channel, end_channel));
if (chosen > end_channel) {
if (chosen <= 6)
chosen = end_channel;
else
chosen = start_channel;
} else if (chosen < start_channel)
chosen = start_channel;
ap->channel = chosen;
}
#else
ap->channel = chosen;
#endif
WL_SOFTAP(("Set auto channel = %d\n", chosen));
dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown));
}
#else
ap->channel = 6;
#endif
channel = ap->channel;
dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel));
if (strnicmp(ap->sec, "open", strlen("open")) == 0) {
wsec = 0;
dev_wlc_intvar_set(dev, "wsec", wsec);
wpa_auth = WPA_AUTH_DISABLED;
dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
} else if (strnicmp(ap->sec, "wep", strlen("wep")) == 0) {
memset(&key, 0, sizeof(key));
wsec = WEP_ENABLED;
dev_wlc_intvar_set(dev, "wsec", wsec);
key.index = 0;
if (wl_iw_parse_wep(ap->key, &key)) {
WL_SOFTAP(("wep key parse err!\n"));
return -1;
}
key.index = htod32(key.index);
key.len = htod32(key.len);
key.algo = htod32(key.algo);
key.flags = htod32(key.flags);
wep = 1;
wpa_auth = WPA_AUTH_DISABLED;
dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
} else if (strnicmp(ap->sec, "wpa2-psk", strlen("wpa2-psk")) == 0) {
wsec_pmk_t psk;
size_t key_len;
wsec = AES_ENABLED;
dev_wlc_intvar_set(dev, "wsec", wsec);
key_len = strlen(ap->key);
if (key_len < WSEC_MIN_PSK_LEN || key_len > WSEC_MAX_PSK_LEN) {
WL_SOFTAP(("passphrase must be between %d and %d characters long\n",
WSEC_MIN_PSK_LEN, WSEC_MAX_PSK_LEN));
return -1;
}
/* anthony: turn all psk-key to 64 char wide in default. */
if ( key_len < WSEC_MAX_PSK_LEN ){
unsigned char output[2*SHA1HashSize];
char key_str_buf[WSEC_MAX_PSK_LEN+1];
/* anthony: call passhash to make hash */
pbkdf2_sha1(ap->key, ap->ssid, strlen(ap->ssid), 4096, output, 32);
/* anthony: turn hex digit to char string */
ptr = key_str_buf;
for (i=0; i<(WSEC_MAX_PSK_LEN/8); i++){
/* anthony: the order is comfirmed in big-endian. It maybe different in little-endian? */
sprintf(ptr, "%02x%02x%02x%02x", (uint)output[i*4], (uint)output[i*4+1], (uint)output[i*4+2], (uint)output[i*4+3]);
ptr += 8;
}
printk("%s: passphase = %s\n", __FUNCTION__, key_str_buf);
psk.key_len = htod16((ushort)WSEC_MAX_PSK_LEN);
memcpy(psk.key, key_str_buf, psk.key_len);
} else {
psk.key_len = htod16((ushort) key_len);
memcpy(psk.key, ap->key, key_len);
}
psk.flags = htod16(WSEC_PASSPHRASE);
dev_wlc_ioctl(dev, WLC_SET_WSEC_PMK, &psk, sizeof(psk));
wpa_auth = WPA2_AUTH_PSK;
dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
} else if (strnicmp(ap->sec, "wpa-psk", strlen("wpa-psk")) == 0) {
wsec_pmk_t psk;
size_t key_len;
wsec = TKIP_ENABLED;
dev_wlc_intvar_set(dev, "wsec", wsec);
key_len = strlen(ap->key);
if (key_len < WSEC_MIN_PSK_LEN || key_len > WSEC_MAX_PSK_LEN) {
WL_SOFTAP(("passphrase must be between %d and %d characters long\n",
WSEC_MIN_PSK_LEN, WSEC_MAX_PSK_LEN));
return -1;
}
/* anthony: turn all psk-key to 64 char wide in default. */
if ( key_len < WSEC_MAX_PSK_LEN ){
unsigned char output[2*SHA1HashSize];
char key_str_buf[WSEC_MAX_PSK_LEN+1];
printk("%s: do passhash...\n", __FUNCTION__);
/* anthony: call passhash to make hash */
pbkdf2_sha1(ap->key, ap->ssid, strlen(ap->ssid), 4096, output, 32);
/* anthony: turn hex digit to char string */
ptr = key_str_buf;
for (i=0; i<(WSEC_MAX_PSK_LEN/8); i++)
{
printk("[%02d]: %08x\n", i, *((unsigned int*)&output[i*4]));
/* anthony: the order is comfirmed in big-endian. It maybe different in little-endian? */
sprintf(ptr, "%02x%02x%02x%02x", (uint)output[i*4], (uint)output[i*4+1], (uint)output[i*4+2], (uint)output[i*4+3]);
ptr += 8;
}
printk("%s: passphase = %s\n", __FUNCTION__, key_str_buf);
psk.key_len = htod16((ushort)WSEC_MAX_PSK_LEN);
memcpy(psk.key, key_str_buf, psk.key_len);
} else {
psk.key_len = htod16((ushort) key_len);
memcpy(psk.key, ap->key, key_len);
}
psk.flags = htod16(WSEC_PASSPHRASE);
dev_wlc_ioctl(dev, WLC_SET_WSEC_PMK, &psk, sizeof(psk));
wpa_auth = WPA_AUTH_PSK;
dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
}
WL_SOFTAP(("ap setup done\n"));
updown = 0;
dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown));
max_assoc = ap->max_scb;
dev_wlc_intvar_set(dev, "maxassoc", max_assoc);
ap_mode = 1;
ap_ssid.SSID_len = strlen(ap->ssid);
strncpy(ap_ssid.SSID, ap->ssid, ap_ssid.SSID_len);
dev_wlc_ioctl(dev, WLC_SET_SSID, &ap_ssid, sizeof(ap_ssid));
dev_wlc_intvar_set(dev, "mpc", mpc);
if (wep)
dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment