Пример #1
0
static int wpa_driver_hostap_scan(void *priv, const u8 *ssid, size_t ssid_len)
{
	struct wpa_driver_hostap_data *drv = priv;
	struct prism2_hostapd_param param;
	int ret;

	if (ssid == NULL) {
		/* Use standard Linux Wireless Extensions ioctl if possible
		 * because some drivers using hostap code in wpa_supplicant
		 * might not support Host AP specific scan request (with SSID
		 * info). */
		return wpa_driver_wext_scan(drv->wext, ssid, ssid_len);
	}

	if (ssid_len > 32)
		ssid_len = 32;

	memset(&param, 0, sizeof(param));
	param.cmd = PRISM2_HOSTAPD_SCAN_REQ;
	param.u.scan_req.ssid_len = ssid_len;
	memcpy(param.u.scan_req.ssid, ssid, ssid_len);
	ret = hostapd_ioctl(drv, &param, sizeof(param), 1);

	/* Not all drivers generate "scan completed" wireless event, so try to
	 * read results after a timeout. */
	eloop_register_timeout(3, 0, wpa_driver_wext_scan_timeout, drv->wext,
			       drv->ctx);

	return ret;
}
Пример #2
0
static int hostap_get_seqnum(const char *ifname, void *priv, const u8 *addr,
			     int idx, u8 *seq)
{
	struct hostap_driver_data *drv = priv;
	struct prism2_hostapd_param *param;
	u8 *buf;
	size_t blen;
	int ret = 0;

	blen = sizeof(*param) + 32;
	buf = os_zalloc(blen);
	if (buf == NULL)
		return -1;

	param = (struct prism2_hostapd_param *) buf;
	param->cmd = PRISM2_GET_ENCRYPTION;
	if (addr == NULL)
		os_memset(param->sta_addr, 0xff, ETH_ALEN);
	else
		os_memcpy(param->sta_addr, addr, ETH_ALEN);
	param->u.crypt.idx = idx;

	if (hostapd_ioctl(drv, param, blen)) {
		printf("Failed to get encryption.\n");
		ret = -1;
	} else {
		os_memcpy(seq, param->u.crypt.seq, 8);
	}
	os_free(buf);

	return ret;
}
Пример #3
0
static int hostap_sta_add(void *priv, struct hostapd_sta_add_params *params)
{
	struct hostap_driver_data *drv = priv;
	struct prism2_hostapd_param param;
	int tx_supp_rates = 0;
	size_t i;

#define WLAN_RATE_1M BIT(0)
#define WLAN_RATE_2M BIT(1)
#define WLAN_RATE_5M5 BIT(2)
#define WLAN_RATE_11M BIT(3)

	for (i = 0; i < params->supp_rates_len; i++) {
		if ((params->supp_rates[i] & 0x7f) == 2)
			tx_supp_rates |= WLAN_RATE_1M;
		if ((params->supp_rates[i] & 0x7f) == 4)
			tx_supp_rates |= WLAN_RATE_2M;
		if ((params->supp_rates[i] & 0x7f) == 11)
			tx_supp_rates |= WLAN_RATE_5M5;
		if ((params->supp_rates[i] & 0x7f) == 22)
			tx_supp_rates |= WLAN_RATE_11M;
	}

	memset(&param, 0, sizeof(param));
	param.cmd = PRISM2_HOSTAPD_ADD_STA;
	memcpy(param.sta_addr, params->addr, ETH_ALEN);
	param.u.add_sta.aid = params->aid;
	param.u.add_sta.capability = params->capability;
	param.u.add_sta.tx_supp_rates = tx_supp_rates;
	return hostapd_ioctl(drv, &param, sizeof(param));
}
Пример #4
0
int hostapd_set_encryption(hostapd *hapd, const char *alg, u8 *addr,
			   int idx, u8 *key, size_t key_len)
{
	struct prism2_hostapd_param *param;
	u8 *buf;
	size_t blen;
	int ret = 0;

	blen = sizeof(*param) + key_len;
	buf = malloc(blen);
	if (buf == NULL)
		return -1;
	memset(buf, 0, blen);

	param = (struct prism2_hostapd_param *) buf;
	param->cmd = PRISM2_SET_ENCRYPTION;
	if (addr == NULL)
		memset(param->sta_addr, 0xff, ETH_ALEN);
	else
		memcpy(param->sta_addr, addr, ETH_ALEN);
	strncpy(param->u.crypt.alg, alg, HOSTAP_CRYPT_ALG_NAME_LEN);
	param->u.crypt.flags = HOSTAP_CRYPT_FLAG_SET_TX_KEY;
	param->u.crypt.idx = idx;
	param->u.crypt.key_len = key_len;
	memcpy((u8 *) (param + 1), key, key_len);

	if (hostapd_ioctl(hapd, param, blen)) {
		printf("Failed to set encryption.\n");
		ret = -1;
	}
	free(buf);

	return ret;
}
Пример #5
0
static int hostap_sta_add(const char *ifname, void *priv, const u8 *addr,
                          u16 aid, u16 capability, u8 *supp_rates,
                          size_t supp_rates_len, int flags,
                          u16 listen_interval)
{
    struct hostap_driver_data *drv = priv;
    struct prism2_hostapd_param param;
    int tx_supp_rates = 0;
    size_t i;

#define WLAN_RATE_1M BIT(0)
#define WLAN_RATE_2M BIT(1)
#define WLAN_RATE_5M5 BIT(2)
#define WLAN_RATE_11M BIT(3)

    for (i = 0; i < supp_rates_len; i++) {
        if ((supp_rates[i] & 0x7f) == 2)
            tx_supp_rates |= WLAN_RATE_1M;
        if ((supp_rates[i] & 0x7f) == 4)
            tx_supp_rates |= WLAN_RATE_2M;
        if ((supp_rates[i] & 0x7f) == 11)
            tx_supp_rates |= WLAN_RATE_5M5;
        if ((supp_rates[i] & 0x7f) == 22)
            tx_supp_rates |= WLAN_RATE_11M;
    }

    memset(&param, 0, sizeof(param));
    param.cmd = PRISM2_HOSTAPD_ADD_STA;
    memcpy(param.sta_addr, addr, ETH_ALEN);
    param.u.add_sta.aid = aid;
    param.u.add_sta.capability = capability;
    param.u.add_sta.tx_supp_rates = tx_supp_rates;
    return hostapd_ioctl(drv, &param, sizeof(param));
}
Пример #6
0
static int hostapd_ioctl_set_generic_elem(struct hostap_driver_data *drv)
{
	struct prism2_hostapd_param *param;
	int res;
	size_t blen, elem_len;

	elem_len = drv->generic_ie_len + drv->wps_ie_len;
	blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + elem_len;
	if (blen < sizeof(*param))
		blen = sizeof(*param);

	param = os_zalloc(blen);
	if (param == NULL)
		return -1;

	param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT;
	param->u.generic_elem.len = elem_len;
	if (drv->generic_ie) {
		os_memcpy(param->u.generic_elem.data, drv->generic_ie,
			  drv->generic_ie_len);
	}
	if (drv->wps_ie) {
		os_memcpy(&param->u.generic_elem.data[drv->generic_ie_len],
			  drv->wps_ie, drv->wps_ie_len);
	}
	wpa_hexdump(MSG_DEBUG, "hostap: Set generic IE",
		    param->u.generic_elem.data, elem_len);
	res = hostapd_ioctl(drv, param, blen);

	os_free(param);

	return res;
}
Пример #7
0
int hostapd_flush(hostapd *hapd)
{
	struct prism2_hostapd_param param;

	memset(&param, 0, sizeof(param));
	param.cmd = PRISM2_HOSTAPD_FLUSH;
	return hostapd_ioctl(hapd, &param, sizeof(param));
}
Пример #8
0
static int hostap_flush(void *priv)
{
	struct hostap_driver_data *drv = priv;
	struct prism2_hostapd_param param;

	memset(&param, 0, sizeof(param));
	param.cmd = PRISM2_HOSTAPD_FLUSH;
	return hostapd_ioctl(drv, &param, sizeof(param));
}
Пример #9
0
static int wpa_driver_hostap_set_key(const char *ifname, void *priv,
				     enum wpa_alg alg, const u8 *addr,
				     int key_idx, int set_tx,
				     const u8 *seq, size_t seq_len,
				     const u8 *key, size_t key_len)
{
	struct hostap_driver_data *drv = priv;
	struct prism2_hostapd_param *param;
	u8 *buf;
	size_t blen;
	int ret = 0;

	blen = sizeof(*param) + key_len;
	buf = os_zalloc(blen);
	if (buf == NULL)
		return -1;

	param = (struct prism2_hostapd_param *) buf;
	param->cmd = PRISM2_SET_ENCRYPTION;
	if (addr == NULL)
		memset(param->sta_addr, 0xff, ETH_ALEN);
	else
		memcpy(param->sta_addr, addr, ETH_ALEN);
	switch (alg) {
	case WPA_ALG_NONE:
		os_strlcpy((char *) param->u.crypt.alg, "NONE",
			   HOSTAP_CRYPT_ALG_NAME_LEN);
		break;
	case WPA_ALG_WEP:
		os_strlcpy((char *) param->u.crypt.alg, "WEP",
			   HOSTAP_CRYPT_ALG_NAME_LEN);
		break;
	case WPA_ALG_TKIP:
		os_strlcpy((char *) param->u.crypt.alg, "TKIP",
			   HOSTAP_CRYPT_ALG_NAME_LEN);
		break;
	case WPA_ALG_CCMP:
		os_strlcpy((char *) param->u.crypt.alg, "CCMP",
			   HOSTAP_CRYPT_ALG_NAME_LEN);
		break;
	default:
		os_free(buf);
		return -1;
	}
	param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
	param->u.crypt.idx = key_idx;
	param->u.crypt.key_len = key_len;
	memcpy((u8 *) (param + 1), key, key_len);

	if (hostapd_ioctl(drv, param, blen)) {
		printf("Failed to set encryption.\n");
		ret = -1;
	}
	free(buf);

	return ret;
}
Пример #10
0
int wpa_driver_hostap_set_key(const char *ifname, wpa_alg alg,
			      unsigned char *addr, int key_idx,
			      int set_tx, u8 *seq, size_t seq_len,
			      u8 *key, size_t key_len)
{
  struct prism2_hostapd_param *param;
  u8 *buf;
  size_t blen;
  int ret = 0;
  char *alg_name;

  switch (alg) {
      case WPA_ALG_NONE:
	alg_name = "none";
	break;
      case WPA_ALG_WEP:
	alg_name = "WEP";
	break;
      case WPA_ALG_TKIP:
	alg_name = "TKIP";
	break;
      case WPA_ALG_CCMP:
	alg_name = "CCMP";
	break;
      default:
	return -1;
  }

  if (seq_len > 8)
    return -2;

  blen = sizeof(*param) + key_len;
  buf = malloc(blen);
  if (buf == NULL)
    return -1;
  memset(buf, 0, blen);

  param = (struct prism2_hostapd_param *) buf;
  param->cmd = PRISM2_SET_ENCRYPTION;
  memset(param->sta_addr, 0xff, ETH_ALEN);

  strncpy(param->u.crypt.alg, alg_name, HOSTAP_CRYPT_ALG_NAME_LEN);
  param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
  param->u.crypt.idx = key_idx;
  memcpy(param->u.crypt.seq, seq, seq_len);
  param->u.crypt.key_len = key_len;
  memcpy((u8 *) (param + 1), key, key_len);

  if (hostapd_ioctl(ifname, param, blen, 1)) {
    ret = -1;
  }
  free(buf);

  return ret;
}
Пример #11
0
static void handle_assoc_resp(hostapd *hapd, struct ieee80211_mgmt *mgmt,
                              size_t len)
{
    u16 status_code, aid;
    struct prism2_hostapd_param param;

    if (hapd->assoc_ap_state != ASSOCIATE) {
        printf("Unexpected association response received from " MACSTR
               "\n", MAC2STR(mgmt->sa));
        return;
    }

    if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_resp)) {
        printf("handle_assoc_resp - too short payload (len=%d)\n",
               len);
        return;
    }

    if (memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) != 0 ||
            memcmp(mgmt->bssid, hapd->conf->assoc_ap_addr, ETH_ALEN) != 0) {
        printf("Received association response from unexpected address "
               "(SA=" MACSTR " BSSID=" MACSTR "\n",
               MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid));
        return;
    }

    status_code = le_to_host16(mgmt->u.assoc_resp.status_code);
    aid = le_to_host16(mgmt->u.assoc_resp.aid);
    aid &= ~(BIT(14) | BIT(15));

    if (status_code != 0) {
        printf("Association (as station) with AP " MACSTR " failed "
               "(status_code=%d)\n",
               MAC2STR(hapd->conf->assoc_ap_addr), status_code);
        /* Try to authenticate again */
        hapd->assoc_ap_state = AUTHENTICATE;
        eloop_register_timeout(5, 0, ieee802_11_sta_authenticate,
                               hapd, NULL);
    }

    printf("Associated (as station) with AP " MACSTR " (aid=%d)\n",
           MAC2STR(hapd->conf->assoc_ap_addr), aid);
    hapd->assoc_ap_aid = aid;
    hapd->assoc_ap_state = ASSOCIATED;

    memset(&param, 0, sizeof(param));
    param.cmd = PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR;
    memcpy(param.sta_addr, hapd->conf->assoc_ap_addr, ETH_ALEN);
    if (hostapd_ioctl(hapd, &param, sizeof(param))) {
        printf("Could not set associated AP address to kernel "
               "driver.\n");
    }
}
Пример #12
0
void remove_sta(hostapd *hapd, struct sta_info *sta)
{
	struct prism2_hostapd_param param;

	ieee802_1x_set_port_enabled(hapd, sta, 0);

	memset(&param, 0, sizeof(param));
	param.cmd = PRISM2_HOSTAPD_REMOVE_STA;
	memcpy(param.sta_addr, sta->addr, ETH_ALEN);
	if (hostapd_ioctl(hapd, &param, sizeof(param))) {
		printf("Could not remove station from kernel driver.\n");
	}
}
Пример #13
0
static int hostap_set_assoc_ap(void *priv, const u8 *addr)
{
    struct hostap_driver_data *drv = priv;
    struct prism2_hostapd_param param;

    memset(&param, 0, sizeof(param));
    param.cmd = PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR;
    memcpy(param.sta_addr, addr, ETH_ALEN);
    if (hostapd_ioctl(drv, &param, sizeof(param)))
        return -1;

    return 0;
}
Пример #14
0
static int hostap_sta_set_flags(void *priv, const u8 *addr,
                                int total_flags, int flags_or, int flags_and)
{
    struct hostap_driver_data *drv = priv;
    struct prism2_hostapd_param param;

    memset(&param, 0, sizeof(param));
    param.cmd = PRISM2_HOSTAPD_SET_FLAGS_STA;
    memcpy(param.sta_addr, addr, ETH_ALEN);
    param.u.set_flags_sta.flags_or = flags_or;
    param.u.set_flags_sta.flags_and = flags_and;
    return hostapd_ioctl(drv, &param, sizeof(param));
}
Пример #15
0
static int hostap_get_inact_sec(void *priv, const u8 *addr)
{
	struct hostap_driver_data *drv = priv;
	struct prism2_hostapd_param param;

	memset(&param, 0, sizeof(param));
	param.cmd = PRISM2_HOSTAPD_GET_INFO_STA;
	memcpy(param.sta_addr, addr, ETH_ALEN);
	if (hostapd_ioctl(drv, &param, sizeof(param))) {
		return -1;
	}

	return param.u.get_info_sta.inactive_sec;
}
Пример #16
0
static int hostap_sta_clear_stats(void *priv, const u8 *addr)
{
	struct hostap_driver_data *drv = priv;
	struct prism2_hostapd_param param;

	memset(&param, 0, sizeof(param));
	param.cmd = PRISM2_HOSTAPD_STA_CLEAR_STATS;
	memcpy(param.sta_addr, addr, ETH_ALEN);
	if (hostapd_ioctl(drv, &param, sizeof(param))) {
		return -1;
	}

	return 0;
}
Пример #17
0
static int hostap_sta_remove(void *priv, const u8 *addr)
{
	struct hostap_driver_data *drv = priv;
	struct prism2_hostapd_param param;

	hostap_sta_set_flags(drv, addr, 0, 0, ~WPA_STA_AUTHORIZED);

	memset(&param, 0, sizeof(param));
	param.cmd = PRISM2_HOSTAPD_REMOVE_STA;
	memcpy(param.sta_addr, addr, ETH_ALEN);
	if (hostapd_ioctl(drv, &param, sizeof(param))) {
		printf("Could not remove station from kernel driver.\n");
		return -1;
	}
	return 0;
}
Пример #18
0
static int hostap_sta_set_flags(void *priv, const u8 *addr,
				int total_flags, int flags_or, int flags_and)
{
	struct hostap_driver_data *drv = priv;
	struct prism2_hostapd_param param;

	if (flags_or & WPA_STA_AUTHORIZED)
		flags_or = BIT(5); /* WLAN_STA_AUTHORIZED */
	if (!(flags_and & WPA_STA_AUTHORIZED))
		flags_and = ~BIT(5);
	else
		flags_and = ~0;
	memset(&param, 0, sizeof(param));
	param.cmd = PRISM2_HOSTAPD_SET_FLAGS_STA;
	memcpy(param.sta_addr, addr, ETH_ALEN);
	param.u.set_flags_sta.flags_or = flags_or;
	param.u.set_flags_sta.flags_and = flags_and;
	return hostapd_ioctl(drv, &param, sizeof(param));
}
Пример #19
0
static int wpa_driver_hostap_set_wpa_ie(struct wpa_driver_hostap_data *drv,
					const u8 *wpa_ie, size_t wpa_ie_len)
{
	struct prism2_hostapd_param *param;
	int res;
	size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + wpa_ie_len;
	if (blen < sizeof(*param))
		blen = sizeof(*param);

	param = os_zalloc(blen);
	if (param == NULL)
		return -1;

	param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT;
	param->u.generic_elem.len = wpa_ie_len;
	os_memcpy(param->u.generic_elem.data, wpa_ie, wpa_ie_len);
	res = hostapd_ioctl(drv, param, blen, 1);

	os_free(param);

	return res;
}
Пример #20
0
static int wpa_driver_hostap_mlme(struct wpa_driver_hostap_data *drv,
				  const u8 *addr, int cmd, int reason_code)
{
	struct prism2_hostapd_param param;
	int ret;

	/* There does not seem to be a better way of deauthenticating or
	 * disassociating with Prism2/2.5/3 than sending the management frame
	 * and then resetting the Port0 to make sure both the AP and the STA
	 * end up in disconnected state. */
	memset(&param, 0, sizeof(param));
	param.cmd = PRISM2_HOSTAPD_MLME;
	memcpy(param.sta_addr, addr, ETH_ALEN);
	param.u.mlme.cmd = cmd;
	param.u.mlme.reason_code = reason_code;
	ret = hostapd_ioctl(drv, &param, sizeof(param), 1);
	if (ret == 0) {
		usleep(100000);
		ret = wpa_driver_hostap_reset(drv, 2);
	}
	return ret;
}
Пример #21
0
static int wpa_driver_hostap_set_wpa_ie(const char *ifname, const char *wpa_ie,
					size_t wpa_ie_len)
{
	struct prism2_hostapd_param *param;
	int res;
	size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + wpa_ie_len;
	if (blen < sizeof(*param))
		blen = sizeof(*param);

	param = (struct prism2_hostapd_param *) malloc(blen);
	if (param == NULL)
		return -1;

	memset(param, 0, blen);
	param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT;
	param->u.generic_elem.len = wpa_ie_len;
	memcpy(param->u.generic_elem.data, wpa_ie, wpa_ie_len);
	res = hostapd_ioctl(ifname, param, blen, 1);

	free(param);

	return res;
}
Пример #22
0
static int hostap_set_encryption(const char *ifname, void *priv,
                                 const char *alg, const u8 *addr,
                                 int idx, const u8 *key, size_t key_len,
                                 int txkey)
{
    struct hostap_driver_data *drv = priv;
    struct prism2_hostapd_param *param;
    u8 *buf;
    size_t blen;
    int ret = 0;

    blen = sizeof(*param) + key_len;
    buf = os_zalloc(blen);
    if (buf == NULL)
        return -1;

    param = (struct prism2_hostapd_param *) buf;
    param->cmd = PRISM2_SET_ENCRYPTION;
    if (addr == NULL)
        memset(param->sta_addr, 0xff, ETH_ALEN);
    else
        memcpy(param->sta_addr, addr, ETH_ALEN);
    os_strlcpy((char *) param->u.crypt.alg, alg,
               HOSTAP_CRYPT_ALG_NAME_LEN);
    param->u.crypt.flags = txkey ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
    param->u.crypt.idx = idx;
    param->u.crypt.key_len = key_len;
    memcpy((u8 *) (param + 1), key, key_len);

    if (hostapd_ioctl(drv, param, blen)) {
        printf("Failed to set encryption.\n");
        ret = -1;
    }
    free(buf);

    return ret;
}
Пример #23
0
static void handle_assoc_cb(hostapd *hapd, struct ieee80211_mgmt *mgmt,
                            size_t len, int reassoc, int ok)
{
    u16 status;
    struct prism2_hostapd_param param;
    struct sta_info *sta;
    int new_assoc = 1;

    if (!ok) {
        hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
                       HOSTAPD_LEVEL_DEBUG,
                       "did not acknowledge association response");
        return;
    }

    if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
                                  sizeof(mgmt->u.assoc_req))) {
        printf("handle_assoc_cb(reassoc=%d) - too short payload "
               "(len=%d)\n", reassoc, len);
        return;
    }

    if (reassoc)
        status = le_to_host16(mgmt->u.reassoc_resp.status_code);
    else
        status = le_to_host16(mgmt->u.assoc_resp.status_code);

    sta = ap_get_sta(hapd, mgmt->da);
    if (!sta) {
        printf("handle_assoc_cb: STA " MACSTR " not found\n",
               MAC2STR(mgmt->da));
        return;
    }

    if (status != WLAN_STATUS_SUCCESS)
        goto fail;

    hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
                   HOSTAPD_LEVEL_INFO, "associated (aid %d)", sta->aid);
    if (sta->flags & WLAN_STA_ASSOC)
        new_assoc = 0;
    sta->flags |= WLAN_STA_ASSOC;

    memset(&param, 0, sizeof(param));
    param.cmd = PRISM2_HOSTAPD_ADD_STA;
    memcpy(param.sta_addr, sta->addr, ETH_ALEN);
    param.u.add_sta.aid = sta->aid;
    param.u.add_sta.capability = sta->capability;
    param.u.add_sta.tx_supp_rates = sta->tx_supp_rates;
    if (hostapd_ioctl(hapd, &param, sizeof(param))) {
        printf("Could not add station to kernel driver.\n");
    }

    if (new_assoc)
        hostapd_new_assoc_sta(hapd, sta);

    if (sta->eapol_sm)
        sta->eapol_sm->portEnabled = TRUE;

fail:
    /* Copy of the association request is not needed anymore */
    if (sta->last_assoc_req) {
        free(sta->last_assoc_req);
        sta->last_assoc_req = NULL;
    }
}
Пример #24
0
static int wpa_driver_hostap_set_key(void *priv, wpa_alg alg,
				     const u8 *addr, int key_idx,
				     int set_tx, const u8 *seq, size_t seq_len,
				     const u8 *key, size_t key_len)
{
	struct wpa_driver_hostap_data *drv = priv;
	struct prism2_hostapd_param *param;
	u8 *buf;
	size_t blen;
	int ret = 0;
	char *alg_name;

	switch (alg) {
	case WPA_ALG_NONE:
		alg_name = "none";
		break;
	case WPA_ALG_WEP:
		alg_name = "WEP";
		break;
	case WPA_ALG_TKIP:
		alg_name = "TKIP";
		break;
	case WPA_ALG_CCMP:
		alg_name = "CCMP";
		break;
	default:
		return -1;
	}

	wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
		   "key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx,
		   (unsigned long) seq_len, (unsigned long) key_len);

	if (seq_len > 8)
		return -2;

	blen = sizeof(*param) + key_len;
	buf = malloc(blen);
	if (buf == NULL)
		return -1;
	memset(buf, 0, blen);

	param = (struct prism2_hostapd_param *) buf;
	param->cmd = PRISM2_SET_ENCRYPTION;
	/* TODO: In theory, STA in client mode can use five keys; four default
	 * keys for receiving (with keyidx 0..3) and one individual key for
	 * both transmitting and receiving (keyidx 0) _unicast_ packets. Now,
	 * keyidx 0 is reserved for this unicast use and default keys can only
	 * use keyidx 1..3 (i.e., default key with keyidx 0 is not supported).
	 * This should be fine for more or less all cases, but for completeness
	 * sake, the driver could be enhanced to support the missing key. */
#if 0
	if (addr == NULL)
		memset(param->sta_addr, 0xff, ETH_ALEN);
	else
		memcpy(param->sta_addr, addr, ETH_ALEN);
#else
	memset(param->sta_addr, 0xff, ETH_ALEN);
#endif
	strncpy((char *) param->u.crypt.alg, alg_name,
		HOSTAP_CRYPT_ALG_NAME_LEN);
	param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
	param->u.crypt.idx = key_idx;
	memcpy(param->u.crypt.seq, seq, seq_len);
	param->u.crypt.key_len = key_len;
	memcpy((u8 *) (param + 1), key, key_len);

	if (hostapd_ioctl(drv, param, blen, 1)) {
		wpa_printf(MSG_WARNING, "Failed to set encryption.");
		show_set_key_error(param);
		ret = -1;
	}
	free(buf);

	return ret;
}