/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <errno.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #define LOG_TAG "WifiNetwork" #include <cutils/log.h> #include "NetworkManager.h" #include "WifiNetwork.h" #include "Supplicant.h" #include "WifiController.h" #include "InterfaceConfig.h" const char *WifiNetwork::PropertyNames[] = { "ssid", "bssid", "psk", "wepkey.1", "wepkey.2", "wepkey.3", "wepkey.4", "defkeyidx", "pri", "hiddenssid", "AllowedKeyManagement", "AllowedProtocols", "AllowedAuthAlgorithms", "AllowedPairwiseCiphers", "AllowedGroupCiphers", "enabled", '\0' }; WifiNetwork::WifiNetwork() { // This is private to restrict copy constructors } WifiNetwork::WifiNetwork(WifiController *c, Supplicant *suppl, const char *data) { mController = c; mSuppl = suppl; char *tmp = strdup(data); char *next = tmp; char *id; char *ssid; char *bssid; char *flags; if (!(id = strsep(&next, "\t"))) LOGE("Failed to extract network id"); if (!(ssid = strsep(&next, "\t"))) LOGE("Failed to extract ssid"); if (!(bssid = strsep(&next, "\t"))) LOGE("Failed to extract bssid"); if (!(flags = strsep(&next, "\t"))) LOGE("Failed to extract flags"); // LOGD("id '%s', ssid '%s', bssid '%s', flags '%s'", id, ssid, bssid, // flags ? flags :"null"); if (id) mNetid = atoi(id); if (ssid) mSsid = strdup(ssid); if (bssid) mBssid = strdup(bssid); mPsk = NULL; memset(mWepKeys, 0, sizeof(mWepKeys)); mDefaultKeyIndex = -1; mPriority = -1; mHiddenSsid = NULL; mAllowedKeyManagement = KeyManagementMask::UNKNOWN; mAllowedProtocols = 0; mAllowedAuthAlgorithms = 0; mAllowedPairwiseCiphers = 0; mAllowedGroupCiphers = 0; mEnabled = true; if (flags && flags[0] != '\0') { if (!strcmp(flags, "[DISABLED]")) mEnabled = false; else LOGW("Unsupported flags '%s'", flags); } char *tmp2; asprintf(&tmp2, "wifi.net.%d", mNetid); mIfaceCfg = new InterfaceConfig(tmp2); free(tmp2); free(tmp); } WifiNetwork::WifiNetwork(WifiController *c, Supplicant *suppl, int networkId) { mController = c; mSuppl = suppl; mNetid = networkId; mSsid = NULL; mBssid = NULL; mPsk = NULL; memset(mWepKeys, 0, sizeof(mWepKeys)); mDefaultKeyIndex = -1; mPriority = -1; mHiddenSsid = NULL; mAllowedKeyManagement = 0; mAllowedProtocols = 0; mAllowedAuthAlgorithms = 0; mAllowedPairwiseCiphers = 0; mAllowedGroupCiphers = 0; mEnabled = false; char *tmp2; asprintf(&tmp2, "wifi.net.%d", mNetid); mIfaceCfg = new InterfaceConfig(tmp2); free(tmp2); } WifiNetwork *WifiNetwork::clone() { WifiNetwork *r = new WifiNetwork(); r->mSuppl = mSuppl; r->mNetid = mNetid; if (mSsid) r->mSsid = strdup(mSsid); if (mBssid) r->mBssid = strdup(mBssid); if (mPsk) r->mPsk = strdup(mPsk); r->mController = mController; memcpy(r->mWepKeys, mWepKeys, sizeof(mWepKeys)); r->mDefaultKeyIndex = mDefaultKeyIndex; r->mPriority = mPriority; if (mHiddenSsid) r->mHiddenSsid = strdup(mHiddenSsid); r->mAllowedKeyManagement = mAllowedKeyManagement; r->mAllowedProtocols = mAllowedProtocols; r->mAllowedAuthAlgorithms = mAllowedAuthAlgorithms; r->mAllowedPairwiseCiphers = mAllowedPairwiseCiphers; r->mAllowedGroupCiphers = mAllowedGroupCiphers; return r; } WifiNetwork::~WifiNetwork() { if (mSsid) free(mSsid); if (mBssid) free(mBssid); if (mPsk) free(mPsk); for (int i = 0; i < 4; i++) { if (mWepKeys[i]) free(mWepKeys[i]); } if (mHiddenSsid) free(mHiddenSsid); if (mIfaceCfg) delete(mIfaceCfg); } int WifiNetwork::refresh() { char buffer[255]; size_t len; len = sizeof(buffer); if (mSuppl->getNetworkVar(mNetid, "psk", buffer, len)) mPsk = strdup(buffer); for (int i = 0; i < 4; i++) { char *name; asprintf(&name, "wep_key%d", i); len = sizeof(buffer); if (mSuppl->getNetworkVar(mNetid, name, buffer, len)) mWepKeys[i] = strdup(buffer); free(name); } len = sizeof(buffer); if (mSuppl->getNetworkVar(mNetid, "wep_tx_keyidx", buffer, len)) mDefaultKeyIndex = atoi(buffer); len = sizeof(buffer); if (mSuppl->getNetworkVar(mNetid, "priority", buffer, len)) mPriority = atoi(buffer); len = sizeof(buffer); if (mSuppl->getNetworkVar(mNetid, "scan_ssid", buffer, len)) mHiddenSsid = strdup(buffer); len = sizeof(buffer); if (mSuppl->getNetworkVar(mNetid, "key_mgmt", buffer, len)) { if (!strcmp(buffer, "NONE")) setAllowedKeyManagement(KeyManagementMask::NONE); else if (index(buffer, ' ')) { char *next = buffer; char *token; uint32_t mask = 0; while((token = strsep(&next, " "))) { if (!strcmp(token, "WPA-PSK")) mask |= KeyManagementMask::WPA_PSK; else if (!strcmp(token, "WPA-EAP")) mask |= KeyManagementMask::WPA_EAP; else if (!strcmp(token, "IEE8021X")) mask |= KeyManagementMask::IEEE8021X; else LOGW("Unsupported key management scheme '%s'" , token); } setAllowedKeyManagement(mask); } else LOGE("Unsupported key management '%s'", buffer); } len = sizeof(buffer); if (mSuppl->getNetworkVar(mNetid, "proto", buffer, len)) { // TODO } len = sizeof(buffer); if (mSuppl->getNetworkVar(mNetid, "auth_alg", buffer, len)) { // TODO } len = sizeof(buffer); if (mSuppl->getNetworkVar(mNetid, "pairwise", buffer, len)) { // TODO } len = sizeof(buffer); if (mSuppl->getNetworkVar(mNetid, "group", buffer, len)) { // TODO } return 0; out_err: LOGE("Refresh failed (%s)",strerror(errno)); return -1; } int WifiNetwork::set(const char *name, const char *value) { char *n_tmp = strdup(name + strlen("wifi.net.")); char *n_next = n_tmp; char *n_local; char *n_rest; int rc = 0; if (!strsep(&n_next, ".")) // skip net id goto out_inval; if (!(n_local = strsep(&n_next, "."))) goto out_inval; n_rest = n_next; // LOGD("set(): var '%s'(%s / %s) = %s", name, n_local, n_rest, value); if (!strcasecmp(n_local, "enabled")) rc = setEnabled(atoi(value)); else if (!strcmp(n_local, "ssid")) rc = setSsid(value); else if (!strcasecmp(n_local, "bssid")) rc = setBssid(value); else if (!strcasecmp(n_local, "psk")) rc = setPsk(value); else if (!strcasecmp(n_local, "wepkey")) rc = setWepKey(atoi(n_rest) -1, value); else if (!strcasecmp(n_local, "defkeyidx")) rc = setDefaultKeyIndex(atoi(value)); else if (!strcasecmp(n_local, "pri")) rc = setPriority(atoi(value)); else if (!strcasecmp(n_local, "hiddenssid")) rc = setHiddenSsid(value); else if (!strcasecmp(n_local, "AllowedKeyManagement")) { uint32_t mask = 0; bool none = false; char *v_tmp = strdup(value); char *v_next = v_tmp; char *v_token; while((v_token = strsep(&v_next, " "))) { if (!strcasecmp(v_token, "NONE")) { mask = KeyManagementMask::NONE; none = true; } else if (!none) { if (!strcasecmp(v_token, "WPA_PSK")) mask |= KeyManagementMask::WPA_PSK; else if (!strcasecmp(v_token, "WPA_EAP")) mask |= KeyManagementMask::WPA_EAP; else if (!strcasecmp(v_token, "IEEE8021X")) mask |= KeyManagementMask::IEEE8021X; else { errno = EINVAL; rc = -1; free(v_tmp); goto out; } } else { errno = EINVAL; rc = -1; free(v_tmp); goto out; } } free(v_tmp); } else if (!strcasecmp(n_local, "AllowedProtocols")) { // TODO } else if (!strcasecmp(n_local, "AllowedPairwiseCiphers")) { // TODO } else if (!strcasecmp(n_local, "AllowedAuthAlgorithms")) { // TODO } else if (!strcasecmp(n_local, "AllowedGroupCiphers")) { // TODO } else { errno = ENOENT; free(n_tmp); return -1; } out: free(n_tmp); return rc; out_inval: errno = EINVAL; free(n_tmp); return -1; } const char *WifiNetwork::get(const char *name, char *buffer, size_t maxsize) { char *n_tmp = strdup(name + strlen("wifi.net.")); char *n_next = n_tmp; char *n_local; char fc[64]; char rc[128]; if (!strsep(&n_next, ".")) // skip net id goto out_inval; if (!(n_local = strsep(&n_next, "."))) goto out_inval; strncpy(fc, n_local, sizeof(fc)); rc[0] = '\0'; if (n_next) strncpy(rc, n_next, sizeof(rc)); free(n_tmp); if (!strcasecmp(fc, "enabled")) snprintf(buffer, maxsize, "%d", getEnabled()); else if (!strcasecmp(fc, "ssid")) { strncpy(buffer, getSsid() ? getSsid() : "none", maxsize); } else if (!strcasecmp(fc, "bssid")) { strncpy(buffer, getBssid() ? getBssid() : "none", maxsize); } else if (!strcasecmp(fc, "psk")) { strncpy(buffer, getPsk() ? getPsk() : "none", maxsize); } else if (!strcasecmp(fc, "wepkey")) { strncpy(buffer, getWepKey(atoi(rc)-1) ? getWepKey(atoi(rc)-1) : "none", maxsize); } else if (!strcasecmp(fc, "defkeyidx")) snprintf(buffer, maxsize, "%d", getDefaultKeyIndex()); else if (!strcasecmp(fc, "pri")) snprintf(buffer, maxsize, "%d", getPriority()); else if (!strcasecmp(fc, "AllowedKeyManagement")) { if (getAllowedKeyManagement() == KeyManagementMask::NONE) strncpy(buffer, "NONE", maxsize); else { char tmp[80] = { '\0' }; if (getAllowedKeyManagement() & KeyManagementMask::WPA_PSK) strcat(tmp, "WPA_PSK "); if (getAllowedKeyManagement() & KeyManagementMask::WPA_EAP) strcat(tmp, "WPA_EAP "); if (getAllowedKeyManagement() & KeyManagementMask::IEEE8021X) strcat(tmp, "IEEE8021X"); if (tmp[0] == '\0') { strncpy(buffer, "(internal error)", maxsize); errno = ENOENT; return NULL; } if (tmp[strlen(tmp)] == ' ') tmp[strlen(tmp)] = '\0'; strncpy(buffer, tmp, maxsize); } } else if (!strcasecmp(fc, "hiddenssid")) { strncpy(buffer, getHiddenSsid() ? getHiddenSsid() : "none", maxsize); } else { strncpy(buffer, "(internal error)", maxsize); errno = ENOENT; return NULL; } return buffer; out_inval: errno = EINVAL; free(n_tmp); return NULL; } int WifiNetwork::setSsid(const char *ssid) { if (mSuppl->setNetworkVar(mNetid, "ssid", ssid)) return -1; if (mSsid) free(mSsid); mSsid = strdup(ssid); return 0; } int WifiNetwork::setBssid(const char *bssid) { if (mSuppl->setNetworkVar(mNetid, "bssid", bssid)) return -1; if (mBssid) free(mBssid); mBssid = strdup(bssid); return 0; } int WifiNetwork::setPsk(const char *psk) { if (mSuppl->setNetworkVar(mNetid, "psk", psk)) return -1; if (mPsk) free(mPsk); mPsk = strdup(psk); return 0; } int WifiNetwork::setWepKey(int idx, const char *key) { char *name; asprintf(&name, "wep_key%d", idx); int rc = mSuppl->setNetworkVar(mNetid, name, key); free(name); if (rc) return -1; if (mWepKeys[idx]) free(mWepKeys[idx]); mWepKeys[idx] = strdup(key); return 0; } int WifiNetwork::setDefaultKeyIndex(int idx) { char val[16]; sprintf(val, "%d", idx); if (mSuppl->setNetworkVar(mNetid, "wep_tx_keyidx", val)) return -1; mDefaultKeyIndex = idx; return 0; } int WifiNetwork::setPriority(int priority) { char val[16]; sprintf(val, "%d", priority); if (mSuppl->setNetworkVar(mNetid, "priority", val)) return -1; mPriority = priority; return 0; } int WifiNetwork::setHiddenSsid(const char *ssid) { if (mSuppl->setNetworkVar(mNetid, "scan_ssid", ssid)) return -1; if (mHiddenSsid) free(mHiddenSsid); mHiddenSsid = strdup(ssid); return 0; } int WifiNetwork::setAllowedKeyManagement(uint32_t mask) { char accum[255]; if (mask == KeyManagementMask::NONE) strcpy(accum, "NONE"); else { if (mask & KeyManagementMask::WPA_PSK) strcat(accum, "WPA_PSK "); if (mask & KeyManagementMask::WPA_EAP) strcat(accum, "WPA_EAP "); if (mask & KeyManagementMask::IEEE8021X) strcat(accum, "IEEE8021X "); } if (mSuppl->setNetworkVar(mNetid, "key_mgmt", accum)) return -1; mAllowedKeyManagement = mask; return 0; } int WifiNetwork::setAllowedProtocols(uint32_t mask) { char accum[255]; accum[0] = '\0'; if (mask & SecurityProtocolMask::WPA) strcpy(accum, "WPA "); if (mask & SecurityProtocolMask::RSN) strcat(accum, "RSN"); if (mSuppl->setNetworkVar(mNetid, "proto", accum)) return -1; mAllowedProtocols = mask; return 0; } int WifiNetwork::setAllowedAuthAlgorithms(uint32_t mask) { char accum[255]; accum[0] = '\0'; if (mask & AuthenticationAlgorithmMask::OPEN) strcpy(accum, "OPEN "); if (mask & AuthenticationAlgorithmMask::SHARED) strcat(accum, "SHARED "); if (mask & AuthenticationAlgorithmMask::LEAP) strcat(accum, "LEAP "); if (mSuppl->setNetworkVar(mNetid, "auth_alg", accum)) return -1; mAllowedAuthAlgorithms = mask; return 0; } int WifiNetwork::setAllowedPairwiseCiphers(uint32_t mask) { char accum[255]; if (mask == PairwiseCiphersMask::NONE) strcpy(accum, "NONE"); else { if (mask & PairwiseCiphersMask::TKIP) strcat(accum, "TKIP "); if (mask & PairwiseCiphersMask::CCMP) strcat(accum, "CCMP "); } if (mSuppl->setNetworkVar(mNetid, "pairwise", accum)) return -1; mAllowedPairwiseCiphers = mask; return 0; } int WifiNetwork::setAllowedGroupCiphers(uint32_t mask) { char accum[255]; if (mask & GroupCiphersMask::WEP40) strcat(accum, "WEP40 "); if (mask & GroupCiphersMask::WEP104) strcat(accum, "WEP104 "); if (mask & GroupCiphersMask::TKIP) strcat(accum, "TKIP "); if (mask & GroupCiphersMask::CCMP) strcat(accum, "CCMP "); if (mSuppl->setNetworkVar(mNetid, "group", accum)) return -1; mAllowedGroupCiphers = mask; return 0; } int WifiNetwork::setEnabled(bool enabled) { if (enabled) { if (getPriority() == -1) { LOGE("Cannot enable network when priority is not set"); errno = EAGAIN; return -1; } if (getAllowedKeyManagement() == KeyManagementMask::UNKNOWN) { LOGE("Cannot enable network when KeyManagement is not set"); errno = EAGAIN; return -1; } } if (mSuppl->enableNetwork(mNetid, enabled)) return -1; mEnabled = enabled; return 0; } int WifiNetwork::registerProperties() { for (const char **p = WifiNetwork::PropertyNames; *p != '\0'; p++) { char *tmp; asprintf(&tmp, "wifi.net.%d.%s", mNetid, *p); if (NetworkManager::Instance()->getPropMngr()->registerProperty(tmp, this)) { free(tmp); return -1; } free(tmp); } return 0; } int WifiNetwork::unregisterProperties() { for (const char **p = WifiNetwork::PropertyNames; *p != '\0'; p++) { char *tmp; asprintf(&tmp, "wifi.net.%d.%s", mNetid, *p); if (NetworkManager::Instance()->getPropMngr()->unregisterProperty(tmp)) LOGW("Unable to remove property '%s' (%s)", tmp, strerror(errno)); free(tmp); } return 0; }