Cumulative patch from commit d2ba3d6bd9336ef8fd761a0cc7999824d4c4da41
d2ba3d6 VLAN: Simplify no-WEP with VLAN check
d66dcb0 WEP: Remove VLAN support from hostapd
646f12a bsd: Add a commit routine
32dc6a3 bsd: Mark define sta_set_flags() only for hostapd
70a867c bsd: Mark the interface down before opening the routing socket
89f4690 bsd: Compute the RSSI level
5dd82c6 bsd: Set IEEE80211_KEY_NOREPLAY in IBSS/AHDEMO mode
cb76af8 bsd: Skip SIOCSIFFFLAGS ioctl when there is no change.
7239ea7 nl80211: Add stop AP mode event API
Change-Id: Ib1c41f2ed18299451f05d0adf808b8b560522c86
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index fbc1ee0..54a2e75 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -451,19 +451,6 @@
os_free(conf->radius);
os_free(conf->radius_das_shared_secret);
hostapd_config_free_vlan(conf);
- if (conf->ssid.dyn_vlan_keys) {
- struct hostapd_ssid *ssid = &conf->ssid;
- size_t i;
- for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) {
- if (ssid->dyn_vlan_keys[i] == NULL)
- continue;
- hostapd_config_free_wep(ssid->dyn_vlan_keys[i]);
- os_free(ssid->dyn_vlan_keys[i]);
- }
- os_free(ssid->dyn_vlan_keys);
- ssid->dyn_vlan_keys = NULL;
- }
-
os_free(conf->time_zone);
#ifdef CONFIG_IEEE80211R
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index b340c1e..9b87686 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -74,8 +74,6 @@
#ifdef CONFIG_FULL_DYNAMIC_VLAN
char *vlan_tagged_interface;
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
- struct hostapd_wep_keys **dyn_vlan_keys;
- size_t max_dyn_vlan_keys;
};
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index ac67001..7925a3e 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -221,30 +221,6 @@
errors++;
}
- if (ssid->dyn_vlan_keys) {
- size_t i;
- for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) {
- const char *ifname;
- struct hostapd_wep_keys *key = ssid->dyn_vlan_keys[i];
- if (key == NULL)
- continue;
- ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan,
- i);
- if (ifname == NULL)
- continue;
-
- idx = key->idx;
- if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_WEP,
- broadcast_ether_addr, idx, 1,
- NULL, 0, key->key[idx],
- key->len[idx])) {
- wpa_printf(MSG_WARNING, "Could not set "
- "dynamic VLAN WEP encryption.");
- errors++;
- }
- }
- }
-
return errors;
}
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 3554e8b..9867581 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -186,114 +186,10 @@
}
-#ifndef CONFIG_NO_VLAN
-static struct hostapd_wep_keys *
-ieee802_1x_group_alloc(struct hostapd_data *hapd, const char *ifname)
-{
- struct hostapd_wep_keys *key;
-
- key = os_zalloc(sizeof(*key));
- if (key == NULL)
- return NULL;
-
- key->default_len = hapd->conf->default_wep_key_len;
-
- if (key->idx >= hapd->conf->broadcast_key_idx_max ||
- key->idx < hapd->conf->broadcast_key_idx_min)
- key->idx = hapd->conf->broadcast_key_idx_min;
- else
- key->idx++;
-
- if (!key->key[key->idx])
- key->key[key->idx] = os_malloc(key->default_len);
- if (key->key[key->idx] == NULL ||
- random_get_bytes(key->key[key->idx], key->default_len)) {
- printf("Could not generate random WEP key (dynamic VLAN).\n");
- os_free(key->key[key->idx]);
- key->key[key->idx] = NULL;
- os_free(key);
- return NULL;
- }
- key->len[key->idx] = key->default_len;
-
- wpa_printf(MSG_DEBUG, "%s: Default WEP idx %d for dynamic VLAN\n",
- ifname, key->idx);
- wpa_hexdump_key(MSG_DEBUG, "Default WEP key (dynamic VLAN)",
- key->key[key->idx], key->len[key->idx]);
-
- if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_WEP,
- broadcast_ether_addr, key->idx, 1,
- NULL, 0, key->key[key->idx],
- key->len[key->idx]))
- printf("Could not set dynamic VLAN WEP encryption key.\n");
-
- hostapd_set_drv_ieee8021x(hapd, ifname, 1);
-
- return key;
-}
-
-
-static struct hostapd_wep_keys *
-ieee802_1x_get_group(struct hostapd_data *hapd, struct hostapd_ssid *ssid,
- size_t vlan_id)
-{
- const char *ifname;
-
- if (vlan_id == 0)
- return &ssid->wep;
-
- if (vlan_id <= ssid->max_dyn_vlan_keys && ssid->dyn_vlan_keys &&
- ssid->dyn_vlan_keys[vlan_id])
- return ssid->dyn_vlan_keys[vlan_id];
-
- wpa_printf(MSG_DEBUG, "IEEE 802.1X: Creating new group "
- "state machine for VLAN ID %lu",
- (unsigned long) vlan_id);
-
- ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id);
- if (ifname == NULL) {
- wpa_printf(MSG_DEBUG, "IEEE 802.1X: Unknown VLAN ID %lu - "
- "cannot create group key state machine",
- (unsigned long) vlan_id);
- return NULL;
- }
-
- if (ssid->dyn_vlan_keys == NULL) {
- int size = (vlan_id + 1) * sizeof(ssid->dyn_vlan_keys[0]);
- ssid->dyn_vlan_keys = os_zalloc(size);
- if (ssid->dyn_vlan_keys == NULL)
- return NULL;
- ssid->max_dyn_vlan_keys = vlan_id;
- }
-
- if (ssid->max_dyn_vlan_keys < vlan_id) {
- struct hostapd_wep_keys **na;
- int size = (vlan_id + 1) * sizeof(ssid->dyn_vlan_keys[0]);
- na = os_realloc(ssid->dyn_vlan_keys, size);
- if (na == NULL)
- return NULL;
- ssid->dyn_vlan_keys = na;
- os_memset(&ssid->dyn_vlan_keys[ssid->max_dyn_vlan_keys + 1], 0,
- (vlan_id - ssid->max_dyn_vlan_keys) *
- sizeof(ssid->dyn_vlan_keys[0]));
- ssid->max_dyn_vlan_keys = vlan_id;
- }
-
- ssid->dyn_vlan_keys[vlan_id] = ieee802_1x_group_alloc(hapd, ifname);
-
- return ssid->dyn_vlan_keys[vlan_id];
-}
-#endif /* CONFIG_NO_VLAN */
-
-
void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
{
struct eapol_authenticator *eapol = hapd->eapol_auth;
struct eapol_state_machine *sm = sta->eapol_sm;
-#ifndef CONFIG_NO_VLAN
- struct hostapd_wep_keys *key = NULL;
- int vlan_id;
-#endif /* CONFIG_NO_VLAN */
if (sm == NULL || !sm->eap_if->eapKeyData)
return;
@@ -302,18 +198,12 @@
MAC2STR(sta->addr));
#ifndef CONFIG_NO_VLAN
- vlan_id = sta->vlan_id;
- if (vlan_id < 0 || vlan_id > MAX_VLAN_ID)
- vlan_id = 0;
-
- if (vlan_id) {
- key = ieee802_1x_get_group(hapd, sta->ssid, vlan_id);
- if (key && key->key[key->idx])
- ieee802_1x_tx_key_one(hapd, sta, key->idx, 1,
- key->key[key->idx],
- key->len[key->idx]);
- } else
+ if (sta->vlan_id > 0 && sta->vlan_id <= MAX_VLAN_ID) {
+ wpa_printf(MSG_ERROR, "Using WEP with vlans is not supported.");
+ return;
+ }
#endif /* CONFIG_NO_VLAN */
+
if (eapol->default_wep_key) {
ieee802_1x_tx_key_one(hapd, sta, eapol->default_wep_key_idx, 1,
eapol->default_wep_key,
diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c
index 9d869b1..4acb12b 100644
--- a/src/drivers/driver_bsd.c
+++ b/src/drivers/driver_bsd.c
@@ -61,10 +61,37 @@
int prev_roaming; /* roaming state to restore on deinit */
int prev_privacy; /* privacy state to restore on deinit */
int prev_wpa; /* wpa state to restore on deinit */
+ enum ieee80211_opmode opmode; /* operation mode */
};
/* Generic functions for hostapd and wpa_supplicant */
+static enum ieee80211_opmode
+get80211opmode(struct bsd_driver_data *drv)
+{
+ struct ifmediareq ifmr;
+
+ (void) memset(&ifmr, 0, sizeof(ifmr));
+ (void) strncpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name));
+
+ if (ioctl(drv->sock, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) {
+ if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) {
+ if (ifmr.ifm_current & IFM_FLAG0)
+ return IEEE80211_M_AHDEMO;
+ else
+ return IEEE80211_M_IBSS;
+ }
+ if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
+ return IEEE80211_M_HOSTAP;
+ if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
+ return IEEE80211_M_MONITOR;
+ if (ifmr.ifm_current & IFM_IEEE80211_MBSS)
+ return IEEE80211_M_MBSS;
+ }
+ return IEEE80211_M_STA;
+}
+
+
static int
bsd_set80211(void *priv, int op, int val, const void *arg, int arg_len)
{
@@ -265,10 +292,15 @@
return -1;
}
- if (enable)
+ if (enable) {
+ if (ifr.ifr_flags & IFF_UP)
+ return 0;
ifr.ifr_flags |= IFF_UP;
- else
+ } else {
+ if (!(ifr.ifr_flags & IFF_UP))
+ return 0;
ifr.ifr_flags &= ~IFF_UP;
+ }
if (ioctl(drv->sock, SIOCSIFFLAGS, &ifr) < 0) {
perror("ioctl[SIOCSIFFLAGS]");
@@ -278,12 +310,21 @@
return 0;
}
+#ifdef HOSTAPD
+static int
+bsd_commit(void *priv)
+{
+ return bsd_ctrl_iface(priv, 1);
+}
+#endif /* HOSTAPD */
+
static int
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)
{
struct ieee80211req_key wk;
+ struct bsd_driver_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%p key_idx=%d set_tx=%d "
"seq_len=%zu key_len=%zu", __func__, alg, addr, key_idx,
@@ -338,6 +379,14 @@
}
if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx)
wk.ik_flags |= IEEE80211_KEY_DEFAULT;
+#ifndef HOSTAPD
+ /*
+ * Ignore replay failures in IBSS and AHDEMO mode.
+ */
+ if (drv->opmode == IEEE80211_M_IBSS ||
+ drv->opmode == IEEE80211_M_AHDEMO)
+ wk.ik_flags |= IEEE80211_KEY_NOREPLAY;
+#endif /* HOSTAPD */
wk.ik_keylen = key_len;
if (seq) {
#ifdef WORDS_BIGENDIAN
@@ -473,6 +522,7 @@
return bsd_ctrl_iface(priv, 1);
}
+#ifdef HOSTAPD
static int
bsd_set_sta_authorized(void *priv, const u8 *addr,
int total_flags, int flags_or, int flags_and)
@@ -492,6 +542,7 @@
IEEE80211_MLME_AUTHORIZE :
IEEE80211_MLME_UNAUTHORIZE, 0, addr);
}
+#endif /* HOSTAPD */
static void
bsd_new_sta(void *priv, void *ctx, u8 addr[IEEE80211_ADDR_LEN])
@@ -1295,6 +1346,11 @@
result->caps = sr->isr_capinfo;
result->qual = sr->isr_rssi;
result->noise = sr->isr_noise;
+ /*
+ * the rssi value reported by the kernel is in 0.5dB steps relative to
+ * the reported noise floor. see ieee80211_node.h for details.
+ */
+ result->level = sr->isr_rssi / 2 + sr->isr_noise;
pos = (u8 *)(result + 1);
@@ -1461,6 +1517,12 @@
drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
if (drv->sock < 0)
goto fail1;
+
+ os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
+ /* Down interface during setup. */
+ if (bsd_ctrl_iface(drv, 0) < 0)
+ goto fail;
+
drv->route = socket(PF_ROUTE, SOCK_RAW, 0);
if (drv->route < 0)
goto fail;
@@ -1468,11 +1530,6 @@
wpa_driver_bsd_event_receive, ctx, drv);
drv->ctx = ctx;
- os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
-
- /* Down interface during setup. */
- if (bsd_ctrl_iface(drv, 0) < 0)
- goto fail;
if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) {
wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s",
@@ -1493,6 +1550,8 @@
if (wpa_driver_bsd_capa(drv))
goto fail;
+ drv->opmode = get80211opmode(drv);
+
return drv;
fail:
close(drv->sock);
@@ -1548,6 +1607,8 @@
.read_sta_data = bsd_read_sta_driver_data,
.sta_disassoc = bsd_sta_disassoc,
.sta_deauth = bsd_sta_deauth,
+ .sta_set_flags = bsd_set_sta_authorized,
+ .commit = bsd_commit,
#else /* HOSTAPD */
.init = wpa_driver_bsd_init,
.deinit = wpa_driver_bsd_deinit,
@@ -1566,6 +1627,5 @@
.hapd_set_ssid = bsd_set_ssid,
.hapd_get_ssid = bsd_get_ssid,
.hapd_send_eapol = bsd_send_eapol,
- .sta_set_flags = bsd_set_sta_authorized,
.set_generic_elem = bsd_set_opt_ie,
};
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 9b0e6d7..2b364c1 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -2455,6 +2455,13 @@
}
+static void nl80211_stop_ap(struct wpa_driver_nl80211_data *drv,
+ struct nlattr **tb)
+{
+ wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_UNAVAILABLE, NULL);
+}
+
+
static void nl80211_connect_failed_event(struct wpa_driver_nl80211_data *drv,
struct nlattr **tb)
{
@@ -2679,6 +2686,9 @@
case NL80211_CMD_RADAR_DETECT:
nl80211_radar_event(drv, tb);
break;
+ case NL80211_CMD_STOP_AP:
+ nl80211_stop_ap(drv, tb);
+ break;
default:
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
"(cmd=%d)", cmd);