summaryrefslogtreecommitdiffstats
path: root/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/wpa/wpa_supplicant/driver_freebsd.c')
-rw-r--r--usr.sbin/wpa/wpa_supplicant/driver_freebsd.c277
1 files changed, 126 insertions, 151 deletions
diff --git a/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c b/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c
index a9c86a6..0ac3c50 100644
--- a/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c
+++ b/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c
@@ -220,7 +220,7 @@ wpa_driver_bsd_set_ssid(void *priv, const char *ssid,
static int
wpa_driver_bsd_set_wpa_ie(struct wpa_driver_bsd_data *drv,
- const char *wpa_ie, size_t wpa_ie_len)
+ const u8 *wpa_ie, size_t wpa_ie_len)
{
struct ieee80211req ireq;
@@ -259,14 +259,6 @@ wpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy)
}
static int
-wpa_driver_bsd_set_wpa(void *priv, int enabled)
-{
- wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
-
- return wpa_driver_bsd_set_wpa_internal(priv, enabled ? 3 : 0, enabled);
-}
-
-static int
wpa_driver_bsd_del_key(struct wpa_driver_bsd_data *drv, int key_idx,
const unsigned char *addr)
{
@@ -290,7 +282,7 @@ wpa_driver_bsd_del_key(struct wpa_driver_bsd_data *drv, int key_idx,
}
static int
-wpa_driver_bsd_set_key(void *priv, wpa_alg alg,
+wpa_driver_bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
const unsigned char *addr, int key_idx, int set_tx,
const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len)
@@ -393,6 +385,26 @@ wpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled)
}
static int
+wpa_driver_bsd_set_auth_alg(void *priv, int auth_alg)
+{
+ struct wpa_driver_bsd_data *drv = priv;
+ int authmode;
+
+ if ((auth_alg & WPA_AUTH_ALG_OPEN) &&
+ (auth_alg & WPA_AUTH_ALG_SHARED))
+ authmode = IEEE80211_AUTH_AUTO;
+ else if (auth_alg & WPA_AUTH_ALG_SHARED)
+ authmode = IEEE80211_AUTH_SHARED;
+ else
+ authmode = IEEE80211_AUTH_OPEN;
+
+ wpa_printf(MSG_DEBUG, "%s alg 0x%x authmode %u",
+ __func__, auth_alg, authmode);
+
+ return set80211param(drv, IEEE80211_IOC_AUTHMODE, authmode);
+}
+
+static int
wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, int reason_code)
{
struct wpa_driver_bsd_data *drv = priv;
@@ -452,6 +464,11 @@ wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
return -1;
}
+ if (wpa_driver_bsd_set_drop_unencrypted(drv, params->drop_unencrypted)
+ < 0)
+ return -1;
+ if (wpa_driver_bsd_set_auth_alg(drv, params->auth_alg) < 0)
+ return -1;
/* XXX error handling is wrong but unclear what to do... */
if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
return -1;
@@ -485,30 +502,11 @@ wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
}
static int
-wpa_driver_bsd_set_auth_alg(void *priv, int auth_alg)
-{
- struct wpa_driver_bsd_data *drv = priv;
- int authmode;
-
- if ((auth_alg & AUTH_ALG_OPEN_SYSTEM) &&
- (auth_alg & AUTH_ALG_SHARED_KEY))
- authmode = IEEE80211_AUTH_AUTO;
- else if (auth_alg & AUTH_ALG_SHARED_KEY)
- authmode = IEEE80211_AUTH_SHARED;
- else
- authmode = IEEE80211_AUTH_OPEN;
-
- wpa_printf(MSG_DEBUG, "%s alg 0x%x authmode %u",
- __func__, auth_alg, authmode);
-
- return set80211param(drv, IEEE80211_IOC_AUTHMODE, authmode);
-}
-
-static int
-wpa_driver_bsd_scan(void *priv, const u8 *ssid, size_t ssid_len)
+wpa_driver_bsd_scan(void *priv, struct wpa_driver_scan_params *params)
{
struct wpa_driver_bsd_data *drv = priv;
struct ieee80211_scan_req sr;
+ int i;
int flags;
/* XXX not true but easiest to perpetuate the myth */
@@ -529,30 +527,21 @@ wpa_driver_bsd_scan(void *priv, const u8 *ssid, size_t ssid_len)
| IEEE80211_IOC_SCAN_NOJOIN
;
sr.sr_duration = IEEE80211_IOC_SCAN_FOREVER;
- if (ssid_len != 0) {
- /* XXX ssid_len must be <= IEEE80211_NWID_LEN */
- memcpy(sr.sr_ssid[sr.sr_nssid].ssid, ssid, ssid_len);
- sr.sr_ssid[sr.sr_nssid].len = ssid_len;
- sr.sr_nssid++;
- }
- if (drv->lastssid_len != 0 &&
- (drv->lastssid_len != ssid_len ||
- memcmp(drv->lastssid, ssid, ssid_len) != 0)) {
- /*
- * If we are scanning because we received a deauth
- * and the scan cache is warm then we'll find the
- * ap there and short circuit a full-blown scan.
- */
- memcpy(sr.sr_ssid[sr.sr_nssid].ssid, drv->lastssid,
- drv->lastssid_len);
- sr.sr_ssid[sr.sr_nssid].len = drv->lastssid_len;
- sr.sr_nssid++;
- /* NB: clear so we don't retry w/o associating first */
- drv->lastssid_len = 0;
- }
- if (sr.sr_nssid != 0) /* NB: check scan cache first */
+ if (params->num_ssids > 0) {
+ sr.sr_nssid = params->num_ssids;
+#if 0
+ /* Boundary check is done by upper layer */
+ if (sr.sr_nssid > IEEE80211_IOC_SCAN_MAX_SSID)
+ sr.sr_nssid = IEEE80211_IOC_SCAN_MAX_SSID;
+#endif
+ /* NB: check scan cache first */
sr.sr_flags |= IEEE80211_IOC_SCAN_CHECK;
-
+}
+ for (i = 0; i < sr.sr_nssid; i++) {
+ sr.sr_ssid[i].len = params->ssids[i].ssid_len;
+ os_memcpy(sr.sr_ssid[i].ssid, params->ssids[i].ssid,
+ sr.sr_ssid[i].len);
+ }
/* NB: net80211 delivers a scan complete event so no need to poll */
return set80211var(drv, IEEE80211_IOC_SCAN_REQ, &sr, sizeof(sr));
}
@@ -654,40 +643,6 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
}
}
-/* Compare function for sorting scan results. Return >0 if @b is consider
- * better. */
-static int
-wpa_scan_result_compar(const void *a, const void *b)
-{
- const struct wpa_scan_result *wa = a;
- const struct wpa_scan_result *wb = b;
-
- /* WPA/WPA2 support preferred */
- if ((wb->wpa_ie_len || wb->rsn_ie_len) &&
- !(wa->wpa_ie_len || wa->rsn_ie_len))
- return 1;
- if (!(wb->wpa_ie_len || wb->rsn_ie_len) &&
- (wa->wpa_ie_len || wa->rsn_ie_len))
- return -1;
-
- /* privacy support preferred */
- if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) &&
- (wb->caps & IEEE80211_CAPINFO_PRIVACY) == 0)
- return 1;
- if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) == 0 &&
- (wb->caps & IEEE80211_CAPINFO_PRIVACY))
- return -1;
-
- /* best/max rate preferred if signal level close enough XXX */
- if (wa->maxrate != wb->maxrate && abs(wb->level - wa->level) < 5)
- return wb->maxrate - wa->maxrate;
-
- /* use freq for channel preference */
-
- /* all things being equal, use signal level */
- return wb->level - wa->level;
-}
-
static int
getmaxrate(const uint8_t rates[15], uint8_t nrates)
{
@@ -715,74 +670,97 @@ iswpaoui(const u_int8_t *frm)
return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
}
-static int
-wpa_driver_bsd_get_scan_results(void *priv,
- struct wpa_scan_result *results,
- size_t max_size)
+
+static void
+wpa_driver_bsd_add_scan_entry(struct wpa_scan_results *res,
+ struct ieee80211req_scan_result *sr)
{
-#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;
+ struct wpa_scan_res *result, **tmp;
+ size_t extra_len;
+ u8 *pos;
+
+ extra_len = 2 + sr->isr_ssid_len;
+ extra_len += 2 + sr->isr_nrates;
+ extra_len += 3; /* ERP IE */
+ extra_len += sr->isr_ie_len;
+
+ result = os_zalloc(sizeof(*result) + extra_len);
+ if (result == NULL)
+ return;
+ os_memcpy(result->bssid, sr->isr_bssid, ETH_ALEN);
+ result->freq = sr->isr_freq;
+ result->beacon_int = sr->isr_intval;
+ result->caps = sr->isr_capinfo;
+ result->qual = sr->isr_rssi;
+ result->noise = sr->isr_noise;
+
+ pos = (u8 *)(result + 1);
+
+ *pos++ = WLAN_EID_SSID;
+ *pos++ = sr->isr_ssid_len;
+ os_memcpy(pos, sr + 1, sr->isr_ssid_len);
+ pos += sr->isr_ssid_len;
+
+ /*
+ * Deal all rates as supported rate.
+ * Because net80211 doesn't report extended supported rate or not.
+ */
+ *pos++ = WLAN_EID_SUPP_RATES;
+ *pos++ = sr->isr_nrates;
+ os_memcpy(pos, sr->isr_rates, sr->isr_nrates);
+ pos += sr->isr_nrates;
+
+ *pos++ = WLAN_EID_ERP_INFO;
+ *pos++ = 1;
+ *pos++ = sr->isr_erp;
+
+ os_memcpy(pos, (u8 *)(sr + 1) + sr->isr_ssid_len, sr->isr_ie_len);
+ pos += sr->isr_ie_len;
+
+ result->ie_len = pos - (u8 *)(result + 1);
+
+ tmp = os_realloc(res->res,
+ (res->num + 1) * sizeof(struct wpa_scan_res *));
+ if (tmp == NULL) {
+ os_free(result);
+ return;
+ }
+ tmp[res->num++] = result;
+ res->res = tmp;
+}
- memset(results, 0, max_size * sizeof(struct wpa_scan_result));
+static 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(drv, IEEE80211_IOC_SCAN_RESULTS, buf, sizeof(buf));
+ len = get80211var(priv, IEEE80211_IOC_SCAN_RESULTS, buf, 24*1024);
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];
- }
- }
+ return NULL;
+
+ res = os_zalloc(sizeof(*res));
+ if (res == NULL)
+ return NULL;
- cp += sr->isr_len, len -= sr->isr_len;
- wsr++;
+ 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;
}
- 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);
+ wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%lu BSSes)",
+ len, (unsigned long)res->num);
- return wsr - results;
-#undef min
+ return (res);
}
+
#define GETPARAM(drv, param, v) \
(((v) = get80211param(drv, param)) != -1)
#define IEEE80211_C_BGSCAN 0x20000000
@@ -941,14 +919,11 @@ struct wpa_driver_ops wpa_driver_bsd_ops = {
.deinit = wpa_driver_bsd_deinit,
.get_bssid = wpa_driver_bsd_get_bssid,
.get_ssid = wpa_driver_bsd_get_ssid,
- .set_wpa = wpa_driver_bsd_set_wpa,
.set_key = wpa_driver_bsd_set_key,
.set_countermeasures = wpa_driver_bsd_set_countermeasures,
- .set_drop_unencrypted = wpa_driver_bsd_set_drop_unencrypted,
- .scan = wpa_driver_bsd_scan,
- .get_scan_results = wpa_driver_bsd_get_scan_results,
+ .scan2 = wpa_driver_bsd_scan,
+ .get_scan_results2 = wpa_driver_bsd_get_scan_results2,
.deauthenticate = wpa_driver_bsd_deauthenticate,
.disassociate = wpa_driver_bsd_disassociate,
.associate = wpa_driver_bsd_associate,
- .set_auth_alg = wpa_driver_bsd_set_auth_alg,
};
OpenPOWER on IntegriCloud