diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net80211/ieee80211_input.c | 163 | ||||
-rw-r--r-- | sys/net80211/ieee80211_var.h | 23 |
2 files changed, 180 insertions, 6 deletions
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c index fa8231f690d..1315553d5f4 100644 --- a/sys/net80211/ieee80211_input.c +++ b/sys/net80211/ieee80211_input.c @@ -1,5 +1,5 @@ /* $NetBSD: ieee80211_input.c,v 1.24 2004/05/31 11:12:24 dyoung Exp $ */ -/* $OpenBSD: ieee80211_input.c,v 1.30 2007/06/21 19:48:48 damien Exp $ */ +/* $OpenBSD: ieee80211_input.c,v 1.31 2007/06/21 20:11:16 damien Exp $ */ /*- * Copyright (c) 2001 Atsushi Onoe * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting @@ -73,6 +73,9 @@ int ieee80211_parse_edca_params_common(struct ieee80211com *, const u_int8_t *); int ieee80211_parse_edca_params(struct ieee80211com *, const u_int8_t *); int ieee80211_parse_wmm_params(struct ieee80211com *, const u_int8_t *); +int ieee80211_parse_rsn(struct ieee80211com *, const u_int8_t *); +enum ieee80211_cipher ieee80211_parse_rsn_cipher(const u_int8_t[]); +enum ieee80211_akm ieee80211_parse_rsn_akm(const u_int8_t[]); void ieee80211_recv_pspoll(struct ieee80211com *, struct mbuf *, int, u_int32_t); int ieee80211_do_slow_print(struct ieee80211com *, int *); @@ -943,6 +946,10 @@ ieee80211_auth_shared(struct ieee80211com *ic, struct ieee80211_frame *wh, (((const u_int8_t *)(p))[2] << 16) | \ (((const u_int8_t *)(p))[3] << 24))) +/*- + * Parse an EDCA Parameter Set Information Element. + * See IEEE Std 802.11e-2005 - Section 7.3.2.27. + */ int ieee80211_parse_edca_params_common(struct ieee80211com *ic, const u_int8_t *frm) @@ -1013,6 +1020,140 @@ ieee80211_parse_wmm_params(struct ieee80211com *ic, const u_int8_t *frm) } /*- + * Parse an RSN Information Element. + * See IEEE Std 802.11i-2004 - Section 7.3.2.25. + */ +int +ieee80211_parse_rsn(struct ieee80211com *ic, const u_int8_t *frm) +{ + const u_int8_t *efrm; + u_int16_t m, n, s; + u_int16_t cap; + enum ieee80211_cipher cipher_group; + u_int akm_mask, cipher_mask; + + efrm = frm + frm[1]; + frm += 2; + + /* check Version field */ + if (frm + 2 > efrm) + return 1; + if (LE_READ_2(frm) != 1) + return 1; + frm += 2; + + /* all fields after the Version field are optional */ + + /* if Cipher Suite missing, default to CCMP */ + cipher_group = cipher_mask = IEEE80211_CIPHER_CCMP; + /* if AKM Suite missing, default to 802.1X */ + akm_mask = IEEE80211_AKM_IEEE8021X; + + /* read Group Cipher Suite field */ + if (frm + 4 > efrm) + return 0; + cipher_group = ieee80211_parse_rsn_cipher(frm); + if (cipher_group == IEEE80211_CIPHER_USEGROUP) + return 1; + frm += 4; + + /* read Pairwise Cipher Suite Count field */ + if (frm + 2 > efrm) + return 0; + m = LE_READ_2(frm); + frm += 2; + + /* read Pairwise Cipher Suite List */ + if (frm + m * 4 > efrm) + return 1; + cipher_mask = IEEE80211_CIPHER_NONE; + while (m-- > 0) { + cipher_mask |= ieee80211_parse_rsn_cipher(frm); + frm += 4; + } + if (cipher_mask & IEEE80211_CIPHER_USEGROUP) { + if (cipher_mask != IEEE80211_CIPHER_USEGROUP) + return 1; + if (cipher_group == IEEE80211_CIPHER_CCMP) + return 1; + cipher_mask = cipher_group; + } + + /* read AKM Suite List Count field */ + if (frm + 2 > efrm) + return 0; + n = LE_READ_2(frm); + frm += 2; + + /* read AKM Suite List */ + if (frm + n * 4 > efrm) + return 1; + akm_mask = IEEE80211_AKM_NONE; + while (n-- > 0) { + akm_mask |= ieee80211_parse_rsn_akm(frm); + frm += 4; + } + + /* read RSN Capabilities field */ + if (frm + 2 > efrm) + return 0; + cap = LE_READ_2(frm); + frm += 2; + + /* read PMKID Count field */ + if (frm + 2 > efrm) + return 0; + s = LE_READ_2(frm); + frm += 2; + + /* read PMKID List */ + if (frm + 16 * s > efrm) + return 1; + while (s-- > 0) { + /* ignore PMKIDs for now */ + frm += 16; + } + + return 0; +} + +enum ieee80211_cipher +ieee80211_parse_rsn_cipher(const u_int8_t selector[4]) +{ + /* from IEEE Std 802.11i-2004 - Table 20da */ + if (memcmp(selector, IEEE80211_OUI, 3) == 0) { + switch (selector[3]) { + case 0: /* use group cipher suite */ + return IEEE80211_CIPHER_USEGROUP; + case 1: /* WEP-40 */ + return IEEE80211_CIPHER_WEP40; + case 2: /* TKIP */ + return IEEE80211_CIPHER_TKIP; + case 3: /* CCMP (RSNA default) */ + return IEEE80211_CIPHER_CCMP; + case 5: /* WEP-104 */ + return IEEE80211_CIPHER_WEP104; + } + } + return IEEE80211_CIPHER_NONE; /* ignore unknown ciphers */ +} + +enum ieee80211_akm +ieee80211_parse_rsn_akm(const u_int8_t selector[4]) +{ + /* from IEEE Std 802.11i-2004 - Table 20dc */ + if (memcmp(selector, IEEE80211_OUI, 3) == 0) { + switch (selector[3]) { + case 1: /* IEEE 802.1X (RSNA default) */ + return IEEE80211_AKM_IEEE8021X; + case 2: /* PSK */ + return IEEE80211_AKM_PSK; + } + } + return IEEE80211_AKM_NONE; /* ignore unknown AKMs */ +} + +/*- * Beacon/Probe response frame format: * [8] Timestamp * [2] Beacon interval @@ -1024,6 +1165,7 @@ ieee80211_parse_wmm_params(struct ieee80211com *ic, const u_int8_t *frm) * [tlv*] DS Parameter Set (802.11g) * [tlv] ERP Information (802.11g) * [tlv] Extended Supported Rates (802.11g) + * [tlv] RSN (802.11i) * [tlv] EDCA Parameter Set (802.11e) * [tlv] QoS Capability (Beacon only, 802.11e) */ @@ -1036,8 +1178,9 @@ ieee80211_recv_probe_resp(struct ieee80211com *ic, struct mbuf *m0, const struct ieee80211_frame *wh; const u_int8_t *frm, *efrm; - const u_int8_t *ssid, *rates, *xrates, *edca, *wmm, *oui; const u_int8_t *tstamp, *bintval, *capinfo, *country; + const u_int8_t *ssid, *rates, *xrates, *edca, *wmm, *oui; + const u_int8_t *rsn, *wpa; u_int8_t chan, bchan, fhindex, erp; u_int16_t fhdwell; int is_new; @@ -1070,7 +1213,7 @@ ieee80211_recv_probe_resp(struct ieee80211com *ic, struct mbuf *m0, tstamp = frm; frm += 8; bintval = frm; frm += 2; capinfo = frm; frm += 2; - ssid = rates = xrates = country = edca = wmm = NULL; + ssid = rates = xrates = country = edca = wmm = rsn = wpa = NULL; bchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan); chan = bchan; fhdwell = 0; @@ -1119,6 +1262,9 @@ ieee80211_recv_probe_resp(struct ieee80211com *ic, struct mbuf *m0, } erp = frm[2]; break; + case IEEE80211_ELEMID_RSN: + rsn = frm; + break; case IEEE80211_ELEMID_EDCAPARMS: edca = frm; break; @@ -1132,6 +1278,9 @@ ieee80211_recv_probe_resp(struct ieee80211com *ic, struct mbuf *m0, oui = frm + 2; if (memcmp(oui, MICROSOFT_OUI, 3) == 0) { switch (oui[3]) { + case 1: /* WPA */ + wpa = frm; + break; case 2: /* WMM */ wmm = frm; break; @@ -1429,6 +1578,7 @@ ieee80211_recv_auth(struct ieee80211com *ic, struct mbuf *m0, * [tlv] SSID * [tlv] Supported rates * [tlv] Extended Supported Rates (802.11g) + * [tlv] RSN (802.11i) * [tlv] QoS Capability (802.11e) */ void @@ -1440,7 +1590,7 @@ ieee80211_recv_assoc_req(struct ieee80211com *ic, struct mbuf *m0, const struct ieee80211_frame *wh; const u_int8_t *frm, *efrm; - const u_int8_t *ssid, *rates, *xrates; + const u_int8_t *ssid, *rates, *xrates, *rsn, *wpa; u_int16_t capinfo, bintval; int reassoc, resp; @@ -1471,7 +1621,7 @@ ieee80211_recv_assoc_req(struct ieee80211com *ic, struct mbuf *m0, bintval = letoh16(*(u_int16_t *)frm); frm += 2; if (reassoc) frm += 6; /* ignore current AP info */ - ssid = rates = xrates = NULL; + ssid = rates = xrates = rsn = wpa = NULL; while (frm < efrm) { switch (*frm) { case IEEE80211_ELEMID_SSID: @@ -1483,6 +1633,9 @@ ieee80211_recv_assoc_req(struct ieee80211com *ic, struct mbuf *m0, case IEEE80211_ELEMID_XRATES: xrates = frm; break; + case IEEE80211_ELEMID_RSN: + rsn = frm; + break; case IEEE80211_ELEMID_QOS_CAP: break; } diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index e1edea5f320..d1c6805f06c 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211_var.h,v 1.24 2007/06/21 18:21:01 damien Exp $ */ +/* $OpenBSD: ieee80211_var.h,v 1.25 2007/06/21 20:11:16 damien Exp $ */ /* $NetBSD: ieee80211_var.h,v 1.7 2004/05/06 03:07:10 dyoung Exp $ */ /*- @@ -89,6 +89,27 @@ enum ieee80211_protmode { }; /* + * 802.11i ciphers. + */ +enum ieee80211_cipher { + IEEE80211_CIPHER_NONE = 0x00000000, + IEEE80211_CIPHER_USEGROUP = 0x00000001, + IEEE80211_CIPHER_WEP40 = 0x00000002, + IEEE80211_CIPHER_TKIP = 0x00000004, + IEEE80211_CIPHER_CCMP = 0x00000008, + IEEE80211_CIPHER_WEP104 = 0x00000010 +}; + +/* + * 802.11i Authentication and Key Management. + */ +enum ieee80211_akm { + IEEE80211_AKM_NONE = 0x00000000, + IEEE80211_AKM_IEEE8021X = 0x00000001, + IEEE80211_AKM_PSK = 0x00000002 +}; + +/* * Channels are specified by frequency and attributes. */ struct ieee80211_channel { |