static void
bsd_new_sta(void *priv, void *ctx, u8 addr[IEEE80211_ADDR_LEN])
{
	struct ieee80211req_wpaie ie;
	int ielen = 0;
	u8 *iebuf = NULL;

	/*
	 * Fetch and validate any negotiated WPA/RSN parameters.
	 */
	memset(&ie, 0, sizeof(ie));
	memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN);
	if (get80211var(priv, IEEE80211_IOC_WPAIE, &ie, sizeof(ie)) < 0) {
		printf("Failed to get WPA/RSN information element.\n");
		goto no_ie;
	}
	iebuf = ie.wpa_ie;
	ielen = ie.wpa_ie[1];
	if (ielen == 0)
		iebuf = NULL;
	else
		ielen += 2;

no_ie:
	drv_event_assoc(ctx, addr, iebuf, ielen, 0);
}
struct wpa_scan_results *
wpa_driver_bsd_get_scan_results2(void *priv)
{
	struct ieee80211req_scan_result *sr;
	struct wpa_scan_results *res;
	int len, rest;
	uint8_t buf[24*1024], *pos;

	len = get80211var(priv, IEEE80211_IOC_SCAN_RESULTS, buf, 24*1024);
	if (len < 0)
		return NULL;

	res = os_zalloc(sizeof(*res));
	if (res == NULL)
		return NULL;

	pos = buf;
	rest = len;
	while (rest >= sizeof(struct ieee80211req_scan_result)) {
		sr = (struct ieee80211req_scan_result *)pos;
		wpa_driver_bsd_add_scan_entry(res, sr);
		pos += sr->isr_len;
		rest -= sr->isr_len;
	}

	wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%lu BSSes)",
		   len, (unsigned long)res->num);

	return res;
}
Example #3
0
static int
bsd_get_seqnum(void *priv, u8 *addr, int idx, u8 *seq)
{
	struct bsd_driver_data *drv = priv;
	hostapd *hapd = drv->hapd;
	struct ieee80211req_key wk;

	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
		"%s: addr=%s idx=%d\n", __func__, ether_sprintf(addr), idx);

	memset(&wk, 0, sizeof(wk));
	if (addr == NULL)
		memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
	else
		memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
	wk.ik_keyix = idx;

	if (get80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)) < 0) {
		printf("Failed to get encryption.\n");
		return -1;
	} else {
		memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
		return 0;
	}
}
Example #4
0
static int
bsd_get_ssid(void *priv, u8 *ssid, int len)
{
	struct bsd_driver_data *drv = priv;

	return get80211var(drv, IEEE80211_IOC_SSID, ssid, IEEE80211_NWID_LEN);
}
static int
wpa_driver_bsd_get_bssid(void *priv, u8 *bssid)
{
	struct wpa_driver_bsd_data *drv = priv;

	return get80211var(drv, IEEE80211_IOC_BSSID,
		bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0;
}
static int
bsd_new_sta(struct bsd_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
{
	struct hostapd_data *hapd = drv->hapd;
	struct hostapd_bss_config *conf = hapd->conf;
	struct sta_info *sta;
	struct ieee80211req_wpaie ie;
	int new_assoc, ielen, res;

	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
		HOSTAPD_LEVEL_INFO, "associated");

	sta = ap_sta_add(hapd, addr);
	if (sta == NULL)
		return -1;
	/*
	 * Fetch and validate any negotiated WPA/RSN parameters.
	 */
	if (conf->wpa) {
		memset(&ie, 0, sizeof(ie));
		memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN);
		if (get80211var(drv, IEEE80211_IOC_WPAIE, &ie, sizeof(ie)) < 0) {
			printf("Failed to get WPA/RSN information element.\n");
			return -1;		/* XXX not right */
		}
		ielen = ie.wpa_ie[1];
		if (ielen == 0) {
			printf("No WPA/RSN information element for station!\n");
			return -1;		/* XXX not right */
		}
		ielen += 2;
		if (sta->wpa_sm == NULL)
			sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
							sta->addr);
		if (sta->wpa_sm == NULL) {
			printf("Failed to initialize WPA state machine\n");
			return -1;
		}
		res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
					  ie.wpa_ie, ielen, NULL, 0);
		if (res != WPA_IE_OK) {
			printf("WPA/RSN information element rejected? "
				"(res %u)\n", res);
			return -1;
		}
	}

	/*
	 * Now that the internal station state is setup
	 * kick the authenticator into action.
	 */
	new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
	sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
	wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
	hostapd_new_assoc_sta(hapd, sta, !new_assoc);
	ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
	return 0;
}
static int
bsd_get_ssid(const char *ifname, void *priv, u8 *buf, int len)
{
	struct bsd_driver_data *drv = priv;
	int ssid_len = get80211var(drv, IEEE80211_IOC_SSID, buf, len);

	wpa_printf(MSG_DEBUG, "%s: ssid=\"%.*s\"", __func__, ssid_len, buf);

	return ssid_len;
}
Example #8
0
static int
bsd_get_ssid(void *priv, u8 *buf, int len)
{
	struct bsd_driver_data *drv = priv;
	hostapd *hapd = drv->hapd;
	int ssid_len = get80211var(priv, IEEE80211_IOC_SSID, buf, len);

	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: ssid=\"%.*s\"\n",
		__func__, ssid_len, buf);

	return ssid_len;
}
static int
wpa_driver_bsd_get_bssid(void *priv, u8 *bssid)
{
	struct bsd_driver_data *drv = priv;
#ifdef SIOCG80211BSSID
	struct ieee80211_bssid bs;

	os_strlcpy(bs.i_name, drv->ifname, sizeof(bs.i_name));
	if (ioctl(drv->sock, SIOCG80211BSSID, &bs) < 0)
		return -1;
	os_memcpy(bssid, bs.i_bssid, sizeof(bs.i_bssid));
	return 0;
#else
	return get80211var(drv, IEEE80211_IOC_BSSID,
		bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0;
#endif
}
static int
bsd_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data,
			 const u8 *addr)
{
	struct ieee80211req_sta_stats stats;

	memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN);
	if (get80211var(priv, IEEE80211_IOC_STA_STATS, &stats, sizeof(stats))
	    > 0) {
		/* XXX? do packets counts include non-data frames? */
		data->rx_packets = stats.is_stats.ns_rx_data;
		data->rx_bytes = stats.is_stats.ns_rx_bytes;
		data->tx_packets = stats.is_stats.ns_tx_data;
		data->tx_bytes = stats.is_stats.ns_tx_bytes;
	}
	return 0;
}
Example #11
0
static int
bsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
	       u8 *seq)
{
	struct ieee80211req_key wk;

	wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d",
		   __func__, ether_sprintf(addr), idx);

	memset(&wk, 0, sizeof(wk));
	if (addr == NULL)
		memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
	else
		memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
	wk.ik_keyix = idx;

	if (get80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)) < 0) {
		printf("Failed to get encryption.\n");
		return -1;
	}

#ifdef WORDS_BIGENDIAN
#ifndef WPA_KEY_RSC_LEN
#define WPA_KEY_RSC_LEN 8
#endif
	{
		/*
		 * wk.ik_keytsc is in host byte order (big endian), need to
		 * swap it to match with the byte order used in WPA.
		 */
		int i;
		u8 tmp[WPA_KEY_RSC_LEN];
		memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
		for (i = 0; i < WPA_KEY_RSC_LEN; i++) {
			seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1];
		}
	}
#else /* WORDS_BIGENDIAN */
	memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
#endif /* WORDS_BIGENDIAN */
	return 0;
}
static int
bsd_get_ssid(void *priv, u8 *ssid, int len)
{
	struct bsd_driver_data *drv = priv;
#ifdef SIOCG80211NWID
	struct ieee80211_nwid nwid;
	struct ifreq ifr;

	os_memset(&ifr, 0, sizeof(ifr));
	os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
	ifr.ifr_data = (void *)&nwid;
	if (ioctl(drv->sock, SIOCG80211NWID, &ifr) < 0 ||
	    nwid.i_len > IEEE80211_NWID_LEN)
		return -1;
	os_memcpy(ssid, nwid.i_nwid, nwid.i_len);
	return nwid.i_len;
#else
	return get80211var(drv, IEEE80211_IOC_SSID, ssid, IEEE80211_NWID_LEN);
#endif
}
static int wpa_driver_bsd_capa(struct bsd_driver_data *drv)
{
#ifdef IEEE80211_IOC_DEVCAPS
/* kernel definitions copied from net80211/ieee80211_var.h */
#define IEEE80211_CIPHER_WEP            0
#define IEEE80211_CIPHER_TKIP           1
#define IEEE80211_CIPHER_AES_CCM        3
#define IEEE80211_CRYPTO_WEP            (1<<IEEE80211_CIPHER_WEP)
#define IEEE80211_CRYPTO_TKIP           (1<<IEEE80211_CIPHER_TKIP)
#define IEEE80211_CRYPTO_AES_CCM        (1<<IEEE80211_CIPHER_AES_CCM)
#define IEEE80211_C_HOSTAP      0x00000400      /* CAPABILITY: HOSTAP avail */
#define IEEE80211_C_WPA1        0x00800000      /* CAPABILITY: WPA1 avail */
#define IEEE80211_C_WPA2        0x01000000      /* CAPABILITY: WPA2 avail */
	struct ieee80211_devcaps_req devcaps;

	if (get80211var(drv, IEEE80211_IOC_DEVCAPS, &devcaps,
			sizeof(devcaps)) < 0) {
		wpa_printf(MSG_ERROR, "failed to IEEE80211_IOC_DEVCAPS: %s",
			   strerror(errno));
		return -1;
	}

	wpa_printf(MSG_DEBUG, "%s: drivercaps=0x%08x,cryptocaps=0x%08x",
		   __func__, devcaps.dc_drivercaps, devcaps.dc_cryptocaps);

	if (devcaps.dc_drivercaps & IEEE80211_C_WPA1)
		drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
			WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
	if (devcaps.dc_drivercaps & IEEE80211_C_WPA2)
		drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
			WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;

	if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_WEP)
		drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |
			WPA_DRIVER_CAPA_ENC_WEP104;
	if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_TKIP)
		drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
	if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_AES_CCM)
		drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;

	if (devcaps.dc_drivercaps & IEEE80211_C_HOSTAP)
		drv->capa.flags |= WPA_DRIVER_FLAGS_AP;
#undef IEEE80211_CIPHER_WEP
#undef IEEE80211_CIPHER_TKIP
#undef IEEE80211_CIPHER_AES_CCM
#undef IEEE80211_CRYPTO_WEP
#undef IEEE80211_CRYPTO_TKIP
#undef IEEE80211_CRYPTO_AES_CCM
#undef IEEE80211_C_HOSTAP
#undef IEEE80211_C_WPA1
#undef IEEE80211_C_WPA2
#else /* IEEE80211_IOC_DEVCAPS */
	/* For now, assume TKIP, CCMP, WPA, WPA2 are supported */
	drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
		WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
		WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
		WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
	drv->capa.enc = WPA_DRIVER_CAPA_ENC_WEP40 |
		WPA_DRIVER_CAPA_ENC_WEP104 |
		WPA_DRIVER_CAPA_ENC_TKIP |
		WPA_DRIVER_CAPA_ENC_CCMP;
	drv->capa.flags |= WPA_DRIVER_FLAGS_AP;
#endif /* IEEE80211_IOC_DEVCAPS */
#ifdef IEEE80211_IOC_SCAN_MAX_SSID
	drv->capa.max_scan_ssids = IEEE80211_IOC_SCAN_MAX_SSID;
#else /* IEEE80211_IOC_SCAN_MAX_SSID */
	drv->capa.max_scan_ssids = 1;
#endif /* IEEE80211_IOC_SCAN_MAX_SSID */
	drv->capa.auth = WPA_DRIVER_AUTH_OPEN |
		WPA_DRIVER_AUTH_SHARED |
		WPA_DRIVER_AUTH_LEAP;
	return 0;
}
Example #14
0
static int
bsd_new_sta(struct bsd_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
{
	struct hostapd_data *hapd = drv->hapd;
	struct hostapd_config *conf = hapd->conf;
	struct sta_info *sta;
	struct ieee80211req_wpaie ie;
	int new_assoc, ielen, res;

	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
		HOSTAPD_LEVEL_INFO, "associated");

	sta = ap_sta_add(hapd, addr);
	if (sta == NULL)
		return -1;
	/*
	 * Fetch and validate any negotiated WPA/RSN parameters.
	 */
	if (conf->wpa) {
		memset(&ie, 0, sizeof(ie));
		memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN);
		if (get80211var(drv, IEEE80211_IOC_WPAIE, &ie, sizeof(ie)) < 0) {
			printf("Failed to get WPA/RSN information element.\n");
			return -1;		/* XXX not right */
		}
		ielen = ie.wpa_ie[1];
		if (ielen == 0) {
			printf("No WPA/RSN information element for station!\n");
			return -1;		/* XXX not right */
		}
		ielen += 2;
		res = wpa_validate_wpa_ie(hapd, sta, ie.wpa_ie, ielen,
				ie.wpa_ie[0] == WLAN_EID_RSN ?
				    HOSTAPD_WPA_VERSION_WPA2 :
				    HOSTAPD_WPA_VERSION_WPA);
		if (res != WPA_IE_OK) {
			printf("WPA/RSN information element rejected? "
				"(res %u)\n", res);
			return -1;
		}
		if (sta->wpa_ie != NULL)
			free(sta->wpa_ie);
		sta->wpa_ie = malloc(ielen);
		if (sta->wpa_ie == NULL) {
			printf("No memory for WPA/RSN information element!\n");
			return -1;
		}
		memcpy(sta->wpa_ie, ie.wpa_ie, ielen);
		sta->wpa_ie_len = ielen;
	} else {
		if (sta->wpa_ie != NULL)
			free(sta->wpa_ie);
		sta->wpa_ie = NULL;
		sta->wpa_ie_len = 0;
	}

	/*
	 * Now that the internal station state is setup
	 * kick the authenticator into action.
	 */
	new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
	sta->flags |= WLAN_STA_ASSOC;
	if (conf->wpa)
		wpa_sm_event(hapd, sta, WPA_ASSOC);
	if (new_assoc)
		hostapd_new_assoc_sta(hapd, sta);
	else if (conf->wpa)
		wpa_sm_event(hapd, sta, WPA_REAUTH);
	ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
	return 0;
}
Example #15
0
static void *
wpa_driver_bsd_init(void *ctx, const char *ifname)
{
	struct wpa_driver_bsd_data *drv;
	struct ieee80211_devcaps_req devcaps;
	int flags;

	drv = malloc(sizeof(*drv));
	if (drv == NULL)
		return NULL;
	memset(drv, 0, sizeof(*drv));
	/*
	 * NB: We require the interface name be mappable to an index.
	 *     This implies we do not support having wpa_supplicant
	 *     wait for an interface to appear.  This seems ok; that
	 *     doesn't belong here; it's really the job of devd.
	 */
	drv->ifindex = if_nametoindex(ifname);
	if (drv->ifindex == 0) {
		wpa_printf(MSG_DEBUG, "%s: interface %s does not exist",
			   __func__, ifname);
		goto fail1;
	}
	drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
	if (drv->sock < 0)
		goto fail1;
	drv->ctx = ctx;
	strncpy(drv->ifname, ifname, sizeof(drv->ifname));

	/*
	 * Mark the interface as down to ensure wpa_supplicant has exclusive
	 * access to the net80211 state machine, do this before opening the
	 * route socket to avoid a false event that the interface disappeared.
	 */
	if (getifflags(drv, &flags) == 0)
		(void) setifflags(drv, flags &~ IFF_UP);

	drv->route = socket(PF_ROUTE, SOCK_RAW, 0);
	if (drv->route < 0)
		goto fail;
	eloop_register_read_sock(drv->route,
		wpa_driver_bsd_event_receive, ctx, drv);

	if (get80211var(drv, IEEE80211_IOC_DEVCAPS, &devcaps, sizeof(devcaps)) < 0) {
		wpa_printf(MSG_DEBUG,
		    "%s: failed to get device capabilities: %s",
		    __func__, strerror(errno));
		goto fail;
	}
	drv->drivercaps = devcaps.dc_drivercaps;
	drv->cryptocaps = devcaps.dc_cryptocaps;

	if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) {
		wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s",
			__func__, strerror(errno));
		goto fail;
	}
	if (!GETPARAM(drv, IEEE80211_IOC_PRIVACY, drv->prev_privacy)) {
		wpa_printf(MSG_DEBUG, "%s: failed to get privacy state: %s",
			__func__, strerror(errno));
		goto fail;
	}
	if (!GETPARAM(drv, IEEE80211_IOC_WPA, drv->prev_wpa)) {
		wpa_printf(MSG_DEBUG, "%s: failed to get wpa state: %s",
			__func__, strerror(errno));
		goto fail;
	}
	if (set80211param(drv, IEEE80211_IOC_ROAMING, IEEE80211_ROAMING_MANUAL) < 0) {
		wpa_printf(MSG_DEBUG, "%s: failed to set wpa_supplicant-based "
			   "roaming: %s", __func__, strerror(errno));
		goto fail;
	}
	if (drv->drivercaps & IEEE80211_C_BGSCAN) {
		/*
		 * Driver does background scanning; force the scan valid
		 * setting to 1.5 x bg scan interval so the scan cache is
		 * always consulted before we force a foreground scan.
		 */ 
		if (setscanvalid(drv) < 0) {
			wpa_printf(MSG_DEBUG,
			    "%s: warning, failed to set scanvalid, scanning "
			    "may be suboptimal: %s", __func__, strerror(errno));
		}
	}
	if (set80211param(drv, IEEE80211_IOC_WPA, 1+2) < 0) {
		wpa_printf(MSG_DEBUG, "%s: failed to enable WPA support %s",
			   __func__, strerror(errno));
		goto fail;
	}

	return drv;
fail:
	close(drv->sock);
fail1:
	free(drv);
	return NULL;
}
Example #16
0
static int
wpa_driver_bsd_get_scan_results(void *priv,
				     struct wpa_scan_result *results,
				     size_t max_size)
{
#define	min(a,b)	((a)>(b)?(b):(a))
	struct wpa_driver_bsd_data *drv = priv;
	uint8_t buf[24*1024];
	const uint8_t *cp, *vp;
	const struct ieee80211req_scan_result *sr;
	struct wpa_scan_result *wsr;
	int len, ielen;

	memset(results, 0, max_size * sizeof(struct wpa_scan_result));

	len = get80211var(drv, IEEE80211_IOC_SCAN_RESULTS, buf, sizeof(buf));
	if (len < 0)
		return -1;
	cp = buf;
	wsr = results;
	while (len >= sizeof(struct ieee80211req_scan_result)) {
		sr = (const struct ieee80211req_scan_result *) cp;
		memcpy(wsr->bssid, sr->isr_bssid, IEEE80211_ADDR_LEN);
		wsr->ssid_len = sr->isr_ssid_len;
		wsr->freq = sr->isr_freq;
		wsr->noise = sr->isr_noise;
		wsr->qual = sr->isr_rssi;
		wsr->level = 0;		/* XXX? */
		wsr->caps = sr->isr_capinfo;
		wsr->maxrate = getmaxrate(sr->isr_rates, sr->isr_nrates);
		vp = ((u_int8_t *)sr) + sr->isr_ie_off;
		memcpy(wsr->ssid, vp, sr->isr_ssid_len);
		if (sr->isr_ie_len > 0) {
			vp += sr->isr_ssid_len;
			ielen = sr->isr_ie_len;
			while (ielen > 0) {
				switch (vp[0]) {
				case IEEE80211_ELEMID_VENDOR:
					if (!iswpaoui(vp))
						break;
					wsr->wpa_ie_len =
					    min(2+vp[1], SSID_MAX_WPA_IE_LEN);
					memcpy(wsr->wpa_ie, vp, wsr->wpa_ie_len);
					break;
				case IEEE80211_ELEMID_RSN:
					wsr->rsn_ie_len =
					    min(2+vp[1], SSID_MAX_WPA_IE_LEN);
					memcpy(wsr->rsn_ie, vp, wsr->rsn_ie_len);
					break;
				}
				ielen -= 2+vp[1];
				vp += 2+vp[1];
			}
		}

		cp += sr->isr_len, len -= sr->isr_len;
		wsr++;
	}
	qsort(results, wsr - results, sizeof(struct wpa_scan_result),
	      wpa_scan_result_compar);

	wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%d BSSes)",
		   len, wsr - results);

	return wsr - results;
#undef min
}