aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2009-01-17 15:25:11 (GMT)
committerJouni Malinen <j@w1.fi>2009-01-17 15:25:11 (GMT)
commit8be1844071eea364c3410a74a35ab8f699f0f7e5 (patch)
tree7bdd20b1a14d135b7c89eea2b0a00a9649a5ec28
parent0d1286e4111af80605d25cc74dc2d493918cbff7 (diff)
downloadhostap-8be1844071eea364c3410a74a35ab8f699f0f7e5.zip
hostap-8be1844071eea364c3410a74a35ab8f699f0f7e5.tar.gz
hostap-8be1844071eea364c3410a74a35ab8f699f0f7e5.tar.bz2
Process received EAPOL frames in IBSS RSN code if in IBSS mode
-rw-r--r--wpa_supplicant/ibss_rsn.c97
-rw-r--r--wpa_supplicant/ibss_rsn.h2
-rw-r--r--wpa_supplicant/wpa_supplicant.c8
3 files changed, 107 insertions, 0 deletions
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index e459081..a35fdc5 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -327,3 +327,100 @@ void ibss_rsn_deinit(struct ibss_rsn *ibss_rsn)
os_free(ibss_rsn);
}
+
+
+static int ibss_rsn_eapol_dst_supp(const u8 *buf, size_t len)
+{
+ const struct ieee802_1x_hdr *hdr;
+ const struct wpa_eapol_key *key;
+ u16 key_info;
+ size_t plen;
+
+ /* TODO: Support other EAPOL packets than just EAPOL-Key */
+
+ if (len < sizeof(*hdr) + sizeof(*key))
+ return -1;
+
+ hdr = (const struct ieee802_1x_hdr *) buf;
+ key = (const struct wpa_eapol_key *) (hdr + 1);
+ plen = be_to_host16(hdr->length);
+
+ if (hdr->version < EAPOL_VERSION) {
+ /* TODO: backwards compatibility */
+ }
+ if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) {
+ wpa_printf(MSG_DEBUG, "RSN: EAPOL frame (type %u) discarded, "
+ "not a Key frame", hdr->type);
+ return -1;
+ }
+ if (plen > len - sizeof(*hdr) || plen < sizeof(*key)) {
+ wpa_printf(MSG_DEBUG, "RSN: EAPOL frame payload size %lu "
+ "invalid (frame size %lu)",
+ (unsigned long) plen, (unsigned long) len);
+ return -1;
+ }
+
+ if (key->type != EAPOL_KEY_TYPE_RSN) {
+ wpa_printf(MSG_DEBUG, "RSN: EAPOL-Key type (%d) unknown, "
+ "discarded", key->type);
+ return -1;
+ }
+
+ key_info = WPA_GET_BE16(key->key_info);
+
+ return !!(key_info & WPA_KEY_INFO_ACK);
+}
+
+
+static int ibss_rsn_process_rx_eapol(struct ibss_rsn *ibss_rsn,
+ struct ibss_rsn_peer *peer,
+ const u8 *buf, size_t len)
+{
+ int supp;
+ u8 *tmp;
+
+ supp = ibss_rsn_eapol_dst_supp(buf, len);
+ if (supp < 0)
+ return -1;
+
+ tmp = os_malloc(len);
+ if (tmp == NULL)
+ return -1;
+ os_memcpy(tmp, buf, len);
+ if (supp) {
+ wpa_printf(MSG_DEBUG, "RSN: IBSS RX EAPOL for Supplicant");
+ wpa_sm_rx_eapol(peer->supp, peer->addr, tmp, len);
+ } else {
+ wpa_printf(MSG_DEBUG, "RSN: IBSS RX EAPOL for Authenticator");
+ wpa_receive(ibss_rsn->auth_group, peer->auth, tmp, len);
+ }
+ os_free(tmp);
+
+ return 1;
+}
+
+
+int ibss_rsn_rx_eapol(struct ibss_rsn *ibss_rsn, const u8 *src_addr,
+ const u8 *buf, size_t len)
+{
+ struct ibss_rsn_peer *peer;
+
+ for (peer = ibss_rsn->peers; peer; peer = peer->next) {
+ if (os_memcmp(src_addr, peer->addr, ETH_ALEN) == 0)
+ return ibss_rsn_process_rx_eapol(ibss_rsn, peer,
+ buf, len);
+ }
+
+ if (ibss_rsn_eapol_dst_supp(buf, len) > 0) {
+ /*
+ * Create new IBSS peer based on an EAPOL message from the peer
+ * Authenticator.
+ */
+ if (ibss_rsn_start(ibss_rsn, src_addr) < 0)
+ return -1;
+ return ibss_rsn_process_rx_eapol(ibss_rsn, ibss_rsn->peers,
+ buf, len);
+ }
+
+ return 0;
+}
diff --git a/wpa_supplicant/ibss_rsn.h b/wpa_supplicant/ibss_rsn.h
index fdcf659..51825fb 100644
--- a/wpa_supplicant/ibss_rsn.h
+++ b/wpa_supplicant/ibss_rsn.h
@@ -39,5 +39,7 @@ struct ibss_rsn {
struct ibss_rsn * ibss_rsn_init(struct wpa_supplicant *wpa_s);
void ibss_rsn_deinit(struct ibss_rsn *ibss_rsn);
int ibss_rsn_start(struct ibss_rsn *ibss_rsn, const u8 *addr);
+int ibss_rsn_rx_eapol(struct ibss_rsn *ibss_rsn, const u8 *src_addr,
+ const u8 *buf, size_t len);
#endif /* IBSS_RSN_H */
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 9836b8a..6d41471 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1552,6 +1552,14 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
return;
}
+#ifdef CONFIG_IBSS_RSN
+ if (wpa_s->current_ssid &&
+ wpa_s->current_ssid->mode == IEEE80211_MODE_IBSS) {
+ ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
+ return;
+ }
+#endif /* CONFIG_IBSS_RSN */
+
/* Source address of the incoming EAPOL frame could be compared to the
* current BSSID. However, it is possible that a centralized
* Authenticator could be using another MAC address than the BSSID of