os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) {
- perror("ioctl[SIOCGIWAP]");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCGIWAP]");
ret = -1;
}
os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN);
os_memset(iwr.u.ap_addr.sa_data, 0, ETH_ALEN);
if (ioctl(drv->ioctl_sock, SIOCSIWAP, &iwr) < 0) {
- perror("ioctl[SIOCSIWAP]");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIWAP]");
ret = -1;
}
iwr.u.essid.length = 32;
if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) {
- perror("ioctl[SIOCGIWESSID]");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCGIWESSID]");
ret = -1;
} else {
ret = iwr.u.essid.length;
iwr.u.essid.length = ssid_len;
if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) {
- perror("ioctl[SIOCSIWESSID]");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIWESSID]");
ret = -1;
}
iwr.u.freq.e = 1;
if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) {
- perror("ioctl[SIOCSIWFREQ]");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIWFREQ]");
ret = -1;
}
wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED");
} else if (os_strncmp(custom, "START", 5) == 0) {
wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED");
+ } else if (os_strncmp(custom, "HANG", 4) == 0) {
+ wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
#endif /* ANDROID */
}
}
(struct sockaddr *) &from, &fromlen);
if (left < 0) {
if (errno != EINTR && errno != EAGAIN)
- perror("recvfrom(netlink)");
+ wpa_printf(MSG_ERROR, "%s: recvfrom(netlink): %d", __func__, errno);
return;
}
os_memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
- perror("ioctl[SIOCGIFFLAGS]");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCGIFFLAGS]");
return -1;
}
*flags = ifr.ifr_flags & 0xffff;
os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
ifr.ifr_flags = flags & 0xffff;
if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
- perror("SIOCSIFFLAGS");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIFFLAGS]");
return -1;
}
return 0;
drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
if (drv->ioctl_sock < 0) {
- perror("socket(PF_INET,SOCK_DGRAM)");
+ wpa_printf(MSG_ERROR, "%s: socket(PF_INET,SOCK_DGRAM)", __func__);
os_free(drv);
return NULL;
}
s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (s < 0) {
- perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
+ wpa_printf(MSG_ERROR, "%s: socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)", __func__);
close(drv->ioctl_sock);
os_free(drv);
return NULL;
local.nl_family = AF_NETLINK;
local.nl_groups = RTMGRP_LINK;
if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {
- perror("bind(netlink)");
+ wpa_printf(MSG_ERROR, "bind(netlink)");
close(s);
close(drv->ioctl_sock);
os_free(drv);
drv->mlme_sock = -1;
#ifdef ANDROID
drv->errors = 0;
- drv->driver_is_loaded = TRUE;
+ drv->driver_is_started = TRUE;
drv->skip_disconnect = 0;
#endif
wpa_driver_wext_finish_drv_init(drv);
os_free(drv);
}
-
/**
* wpa_driver_wext_scan_timeout - Scan timeout to report scan completion
* @eloop_ctx: Unused
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
}
+/**
+ * wpa_driver_wext_set_scan_timeout - Set scan timeout to report scan completion
+ * @priv: Pointer to private wext data from wpa_driver_wext_init()
+ *
+ * This function can be used to set registered timeout when starting a scan to
+ * generate a scan completed event if the driver does not report this.
+ */
+static void wpa_driver_wext_set_scan_timeout(void *priv)
+{
+ struct wpa_driver_wext_data *drv = priv;
+ int timeout = 10; /* In case scan A and B bands it can be long */
+
+ /* Not all drivers generate "scan completed" wireless event, so try to
+ * read results after a timeout. */
+ if (drv->scan_complete_events) {
+ /*
+ * The driver seems to deliver SIOCGIWSCAN events to notify
+ * when scan is complete, so use longer timeout to avoid race
+ * conditions with scanning and following association request.
+ */
+ timeout = 30;
+ }
+ wpa_printf(MSG_DEBUG, "Scan requested - scan timeout %d seconds",
+ timeout);
+ eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
+ eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, drv,
+ drv->ctx);
+}
/**
* wpa_driver_wext_scan - Request the driver to initiate scan
{
struct wpa_driver_wext_data *drv = priv;
struct iwreq iwr;
- int ret = 0, timeout;
+ int ret = 0;
struct iw_scan_req req;
#ifdef ANDROID
struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx);
}
if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) {
- perror("ioctl[SIOCSIWSCAN]");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIWSCAN]");
ret = -1;
}
- /* Not all drivers generate "scan completed" wireless event, so try to
- * read results after a timeout. */
- timeout = 5;
- if (drv->scan_complete_events) {
- /*
- * The driver seems to deliver SIOCGIWSCAN events to notify
- * when scan is complete, so use longer timeout to avoid race
- * conditions with scanning and following association request.
- */
- timeout = 30;
+ wpa_driver_wext_set_scan_timeout(priv);
+
+ return ret;
+}
+
+/**
+ * wpa_driver_wext_combo_scan - Request the driver to initiate combo scan
+ * @priv: Pointer to private wext data from wpa_driver_wext_init()
+ * @ssid_ptr: Pointer to current SSID from configuration list or %NULL to
+ * scan for all SSIDs (either active scan with broadcast SSID or passive
+ * scan)
+ * @ssid_conf: SSID list from the configuration
+ * Returns: 0 on success, -1 on failure
+ * Also updates @ssid_ptr to next specific scan item
+ */
+int wpa_driver_wext_combo_scan(void *priv, struct wpa_ssid **ssid_ptr,
+ struct wpa_ssid *ssid_conf)
+{
+ char buf[WEXT_CSCAN_BUF_LEN];
+ struct wpa_driver_wext_data *drv = priv;
+ struct iwreq iwr;
+ int ret = 0, timeout, i = 0, bp;
+ struct wpa_ssid *ssid, *ssid_orig;
+ u8 *ssid_nm = NULL;
+ size_t ssid_len = 0;
+
+ struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx);
+ int scan_probe_flag = 0;
+
+ if (!drv->driver_is_started) {
+ wpa_printf(MSG_DEBUG, "%s: Driver stopped", __func__);
+ return -1;
}
- wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
- "seconds", ret, timeout);
- eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
- eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, drv,
- drv->ctx);
+
+ wpa_printf(MSG_DEBUG, "%s: Start", __func__);
+
+ /* Set list of SSIDs */
+ ssid_orig = (*ssid_ptr);
+ ssid = (*ssid_ptr) ? (*ssid_ptr) : ssid_conf;
+ bp = WEXT_CSCAN_HEADER_SIZE;
+ os_memcpy(buf, WEXT_CSCAN_HEADER, bp);
+ while (i < WEXT_CSCAN_AMOUNT) {
+ if ((bp + IW_ESSID_MAX_SIZE + 10) >= (int)sizeof(buf))
+ break;
+ *ssid_ptr = ssid;
+ if (ssid == NULL)
+ break;
+ if (!ssid->disabled && ssid->scan_ssid) {
+ wpa_printf(MSG_DEBUG, "For Scan: %s", ssid->ssid);
+ buf[bp++] = WEXT_CSCAN_SSID_SECTION;
+ buf[bp++] = ssid->ssid_len;
+ os_memcpy(&buf[bp], ssid->ssid, ssid->ssid_len);
+ bp += ssid->ssid_len;
+ i++;
+ }
+ ssid = ssid->next;
+ }
+
+ /* Set list of channels */
+ buf[bp++] = WEXT_CSCAN_CHANNEL_SECTION;
+ buf[bp++] = 0;
+
+ /* Set passive dwell time (default is 250) */
+ buf[bp++] = WEXT_CSCAN_PASV_DWELL_SECTION;
+ buf[bp++] = (u8)WEXT_CSCAN_PASV_DWELL_TIME;
+ buf[bp++] = (u8)(WEXT_CSCAN_PASV_DWELL_TIME >> 8);
+
+ /* Set home dwell time (default is 40) */
+ buf[bp++] = WEXT_CSCAN_HOME_DWELL_SECTION;
+ buf[bp++] = (u8)WEXT_CSCAN_HOME_DWELL_TIME;
+ buf[bp++] = (u8)(WEXT_CSCAN_HOME_DWELL_TIME >> 8);
+
+ os_memset(&iwr, 0, sizeof(iwr));
+ os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+ iwr.u.data.pointer = buf;
+ iwr.u.data.length = bp;
+
+ if ((ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr)) < 0) {
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (cscan): %d", ret);
+ *ssid_ptr = ssid_orig;
+ goto old_scan;
+ }
+
+ wpa_driver_wext_set_scan_timeout(priv);
return ret;
+
+old_scan:
+ if (*ssid_ptr) {
+ ssid_nm = (*ssid_ptr)->ssid;
+ ssid_len = (*ssid_ptr)->ssid_len;
+ }
+
+ return wpa_driver_wext_scan(priv, ssid_nm, ssid_len);
}
"trying larger buffer (%lu bytes)",
(unsigned long) res_buf_len);
} else {
- perror("ioctl[SIOCGIWSCAN]");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCGIWSCAN]: %d", errno);
os_free(res_buf);
return NULL;
}
sizeof(range->enc_capa);
if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) {
- perror("ioctl[SIOCGIWRANGE]");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCGIRANGE]");
os_free(range);
return -1;
} else if (iwr.u.data.length >= minlen &&
ret = ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr);
if (ret < 0)
- perror("ioctl[SIOCSIWENCODEEXT] PMK");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIWENCODEEXT] PMK");
os_free(ext);
return ret;
ret = -2;
}
- perror("ioctl[SIOCSIWENCODEEXT]");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIWENCODEEXT]");
}
os_free(ext);
iwr.u.encoding.length = key_len;
if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
- perror("ioctl[SIOCSIWENCODE]");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIWENCODE]");
ret = -1;
}
iwr.u.encoding.pointer = (caddr_t) NULL;
iwr.u.encoding.length = 0;
if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
- perror("ioctl[SIOCSIWENCODE] (set_tx)");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIWENCODE] (set_tx)");
ret = -1;
}
}
iwr.u.data.length = sizeof(mlme);
if (ioctl(drv->ioctl_sock, SIOCSIWMLME, &iwr) < 0) {
- perror("ioctl[SIOCSIWMLME]");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIWMLME]");
ret = -1;
}
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) {
- perror("ioctl[SIOCGIWMODE]");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCGIWMODE]");
iwr.u.mode = IW_MODE_INFRA;
}
iwr.u.data.length = ie_len;
if (ioctl(drv->ioctl_sock, SIOCSIWGENIE, &iwr) < 0) {
- perror("ioctl[SIOCSIWGENIE]");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIWGENIE]");
ret = -1;
}
}
if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
- perror("ioctl[SIOCSIWENCODE]");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIWENCODE]");
ret = -1;
}
}
if (errno != EBUSY) {
- perror("ioctl[SIOCSIWMODE]");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIWMODE]");
goto done;
}
* down, try to set the mode again, and bring it back up.
*/
if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) {
- perror("ioctl[SIOCGIWMODE]");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCGIWMODE]");
goto done;
}
/* Try to set the mode again while the interface is down */
iwr.u.mode = new_mode;
if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0)
- perror("ioctl[SIOCSIWMODE]");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIWMODE]");
else
ret = 0;
if (ioctl(drv->ioctl_sock, SIOCSIWPMKSA, &iwr) < 0) {
if (errno != EOPNOTSUPP)
- perror("ioctl[SIOCSIWPMKSA]");
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPMKSA]");
ret = -1;
}
wpa_printf(MSG_DEBUG, "%s %s len = %d", __func__, cmd, buf_len);
- if (!drv->driver_is_loaded && (os_strcasecmp(cmd, "START") != 0)) {
+ if (!drv->driver_is_started && (os_strcasecmp(cmd, "START") != 0)) {
wpa_printf(MSG_ERROR,"WEXT: Driver not initialized yet");
return -1;
}
if (os_strcasecmp(cmd, "RSSI-APPROX") == 0) {
os_strncpy(cmd, "RSSI", MAX_DRV_CMD_SIZE);
- }
- else if( os_strncasecmp(cmd, "SCAN-CHANNELS", 13) == 0 ) {
+ } else if( os_strncasecmp(cmd, "SCAN-CHANNELS", 13) == 0 ) {
int no_of_chan;
no_of_chan = atoi(cmd + 13);
os_snprintf(cmd, MAX_DRV_CMD_SIZE, "COUNTRY %s",
wpa_driver_get_country_code(no_of_chan));
- }
- else if (os_strcasecmp(cmd, "STOP") == 0) {
+ } else if (os_strcasecmp(cmd, "STOP") == 0) {
if ((wpa_driver_wext_get_ifflags(drv, &flags) == 0) &&
(flags & IFF_UP)) {
wpa_printf(MSG_ERROR, "WEXT: %s when iface is UP", cmd);
wpa_driver_wext_set_ifflags(drv, flags & ~IFF_UP);
}
- }
- else if( os_strcasecmp(cmd, "RELOAD") == 0 ) {
+ } else if( os_strcasecmp(cmd, "RELOAD") == 0 ) {
wpa_printf(MSG_DEBUG,"Reload command");
wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
return ret;
iwr.u.data.pointer = buf;
iwr.u.data.length = buf_len;
- if ((ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr)) < 0) {
- perror("ioctl[SIOCSIWPRIV]");
- }
+ ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr);
if (ret < 0) {
wpa_printf(MSG_ERROR, "%s failed (%d): %s", __func__, ret, cmd);
drv->errors = 0;
wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
}
- }
- else {
+ } else {
drv->errors = 0;
ret = 0;
if ((os_strcasecmp(cmd, "RSSI") == 0) ||
(os_strcasecmp(cmd, "LINKSPEED") == 0) ||
- (os_strcasecmp(cmd, "MACADDR") == 0)) {
+ (os_strcasecmp(cmd, "MACADDR") == 0) ||
+ (os_strcasecmp(cmd, "GETPOWER") == 0) ||
+ (os_strcasecmp(cmd, "GETBAND") == 0)) {
ret = strlen(buf);
- }
- else if (os_strcasecmp(cmd, "START") == 0) {
- drv->driver_is_loaded = TRUE;
+ } else if (os_strcasecmp(cmd, "START") == 0) {
+ drv->driver_is_started = TRUE;
/* os_sleep(0, WPA_DRIVER_WEXT_WAIT_US);
wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED"); */
- }
- else if (os_strcasecmp(cmd, "STOP") == 0) {
- drv->driver_is_loaded = FALSE;
+ } else if (os_strcasecmp(cmd, "STOP") == 0) {
+ drv->driver_is_started = FALSE;
/* wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED"); */
}
wpa_printf(MSG_DEBUG, "%s %s len = %d, %d", __func__, buf, ret, strlen(buf));
.set_countermeasures = wpa_driver_wext_set_countermeasures,
.set_drop_unencrypted = wpa_driver_wext_set_drop_unencrypted,
.scan = wpa_driver_wext_scan,
+ .combo_scan = wpa_driver_wext_combo_scan,
.get_scan_results2 = wpa_driver_wext_get_scan_results,
.deauthenticate = wpa_driver_wext_deauthenticate,
.disassociate = wpa_driver_wext_disassociate,