summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordamien <damien@openbsd.org>2008-09-27 15:00:08 +0000
committerdamien <damien@openbsd.org>2008-09-27 15:00:08 +0000
commitb4e72b721e234afcd54142e3d4541af76f7f628f (patch)
treea24bda41fc626e73302a2a443eadaa6d9f66bb33
parentsync (diff)
downloadwireguard-openbsd-b4e72b721e234afcd54142e3d4541af76f7f628f.tar.xz
wireguard-openbsd-b4e72b721e234afcd54142e3d4541af76f7f628f.zip
Add some inline functions to test the presence of optional 802.11
header fields (Sequence Control, Address 4, QoS Control, +HTC) and use them where appropriate. Add ieee80211_get_qos() inline function to extract the QoS control field of an 802.11 header instead of duplicating the same scary code everywhere (the location of this field depends on the presence of an Address 4 field). Export ieee80211_up_to_ac() so that drivers can select the access category to use based on the TID subfield of the QoS Control field. Define more QoS-related bits for the RSN Capabilities field of RSN IE (will be used later).
-rw-r--r--sys/net80211/ieee80211.h56
-rw-r--r--sys/net80211/ieee80211_crypto_ccmp.c54
-rw-r--r--sys/net80211/ieee80211_crypto_tkip.c42
-rw-r--r--sys/net80211/ieee80211_input.c49
-rw-r--r--sys/net80211/ieee80211_output.c3
-rw-r--r--sys/net80211/ieee80211_proto.h5
6 files changed, 98 insertions, 111 deletions
diff --git a/sys/net80211/ieee80211.h b/sys/net80211/ieee80211.h
index dce9b327d2c..065cf011033 100644
--- a/sys/net80211/ieee80211.h
+++ b/sys/net80211/ieee80211.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211.h,v 1.46 2008/09/01 19:55:21 damien Exp $ */
+/* $OpenBSD: ieee80211.h,v 1.47 2008/09/27 15:00:08 damien Exp $ */
/* $NetBSD: ieee80211.h,v 1.6 2004/04/30 23:51:53 dyoung Exp $ */
/*-
@@ -237,6 +237,52 @@ struct ieee80211_frame_cfend { /* NB: also CF-End+CF-Ack */
/* FCS */
} __packed;
+#ifdef _KERNEL
+static __inline int
+ieee80211_has_seq(const struct ieee80211_frame *wh)
+{
+ return (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=
+ IEEE80211_FC0_TYPE_CTL;
+}
+
+static __inline int
+ieee80211_has_addr4(const struct ieee80211_frame *wh)
+{
+ return (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) ==
+ IEEE80211_FC1_DIR_DSTODS;
+}
+
+static __inline int
+ieee80211_has_qos(const struct ieee80211_frame *wh)
+{
+ return (wh->i_fc[0] &
+ (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) ==
+ (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS);
+}
+
+static __inline int
+ieee80211_has_htc(const struct ieee80211_frame *wh)
+{
+ return (wh->i_fc[1] & IEEE80211_FC1_ORDER) &&
+ (ieee80211_has_qos(wh) ||
+ (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
+ IEEE80211_FC0_TYPE_MGT);
+}
+
+static __inline u_int16_t
+ieee80211_get_qos(const struct ieee80211_frame *wh)
+{
+ const u_int8_t *frm;
+
+ if (ieee80211_has_addr4(wh))
+ frm = ((const struct ieee80211_qosframe_addr4 *)wh)->i_qos;
+ else
+ frm = ((const struct ieee80211_qosframe *)wh)->i_qos;
+
+ return letoh16(*(const u_int16_t *)frm);
+}
+#endif /* _KERNEL */
+
/*
* Capability Information field (see 7.3.1.4).
*/
@@ -336,6 +382,14 @@ enum {
*/
#define IEEE80211_RSNCAP_PREAUTH 0x0001
#define IEEE80211_RSNCAP_NOPAIRWISE 0x0002
+#define IEEE80211_RSNCAP_PTKSA_RCNT_MASK 0x000c
+#define IEEE80211_RSNCAP_PTKSA_RCNT_SHIFT 2
+#define IEEE80211_RSNCAP_GTKSA_RCNT_MASK 0x0030
+#define IEEE80211_RSNCAP_GTKSA_RCNT_SHIFT 4
+#define IEEE80211_RSNCAP_RCNT1 0
+#define IEEE80211_RSNCAP_RCNT2 1
+#define IEEE80211_RSNCAP_RCNT4 2
+#define IEEE80211_RSNCAP_RCNT16 3
#define IEEE80211_RSNCAP_MFPR 0x0040 /* 11w */
#define IEEE80211_RSNCAP_MFPC 0x0080 /* 11w */
#define IEEE80211_RSNCAP_PEERKEYENA 0x0200
diff --git a/sys/net80211/ieee80211_crypto_ccmp.c b/sys/net80211/ieee80211_crypto_ccmp.c
index 5638bfd95c5..02176e1bfd8 100644
--- a/sys/net80211/ieee80211_crypto_ccmp.c
+++ b/sys/net80211/ieee80211_crypto_ccmp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_crypto_ccmp.c,v 1.6 2008/08/12 17:54:57 damien Exp $ */
+/* $OpenBSD: ieee80211_crypto_ccmp.c,v 1.7 2008/09/27 15:00:08 damien Exp $ */
/*-
* Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>
@@ -101,9 +101,7 @@ ieee80211_ccmp_phase1(rijndael_ctx *ctx, const struct ieee80211_frame *wh,
*aad &= ~(IEEE80211_FC1_RETRY | IEEE80211_FC1_PWR_MGT |
IEEE80211_FC1_MORE_DATA);
/* 11n: conditionnally mask order bit */
- if ((wh->i_fc[0] &
- (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) ==
- (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS))
+ if (ieee80211_has_htc(wh))
*aad &= ~IEEE80211_FC1_ORDER;
aad++;
IEEE80211_ADDR_COPY(aad, wh->i_addr1); aad += IEEE80211_ADDR_LEN;
@@ -111,26 +109,13 @@ ieee80211_ccmp_phase1(rijndael_ctx *ctx, const struct ieee80211_frame *wh,
IEEE80211_ADDR_COPY(aad, wh->i_addr3); aad += IEEE80211_ADDR_LEN;
*aad++ = wh->i_seq[0] & ~0xf0;
*aad++ = 0;
- if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) ==
- IEEE80211_FC1_DIR_DSTODS) {
- const struct ieee80211_frame_addr4 *wh4 =
- (const struct ieee80211_frame_addr4 *)wh;
- IEEE80211_ADDR_COPY(aad, wh4->i_addr4);
+ if (ieee80211_has_addr4(wh)) {
+ IEEE80211_ADDR_COPY(aad,
+ ((const struct ieee80211_frame_addr4 *)wh)->i_addr4);
aad += IEEE80211_ADDR_LEN;
- if ((wh->i_fc[0] &
- (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) ==
- (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS)) {
- const struct ieee80211_qosframe_addr4 *qwh4 =
- (const struct ieee80211_qosframe_addr4 *)wh;
- *aad++ = tid = qwh4->i_qos[0] & 0x0f;
- *aad++ = 0;
- }
- } else if ((wh->i_fc[0] &
- (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) ==
- (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS)) {
- const struct ieee80211_qosframe *qwh =
- (const struct ieee80211_qosframe *)wh;
- *aad++ = tid = qwh->i_qos[0] & 0x0f;
+ }
+ if (ieee80211_has_qos(wh)) {
+ *aad++ = tid = ieee80211_get_qos(wh) & IEEE80211_QOS_TID;
*aad++ = 0;
}
@@ -343,25 +328,12 @@ ieee80211_ccmp_decrypt(struct ieee80211com *ic, struct mbuf *m0,
return NULL;
}
- /* retrieve last seen packet number for this frame type/TID */
- if ((wh->i_fc[0] &
- (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) ==
- (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS)) {
- u_int8_t tid;
- if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) ==
- IEEE80211_FC1_DIR_DSTODS) {
- struct ieee80211_qosframe_addr4 *qwh4 =
- (struct ieee80211_qosframe_addr4 *)wh;
- tid = qwh4->i_qos[0] & 0x0f;
- } else {
- struct ieee80211_qosframe *qwh =
- (struct ieee80211_qosframe *)wh;
- tid = qwh->i_qos[0] & 0x0f;
- }
+ /* retrieve last seen packet number for this frame type/priority */
+ if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
+ IEEE80211_FC0_TYPE_DATA) {
+ u_int8_t tid = ieee80211_has_qos(wh) ?
+ ieee80211_get_qos(wh) & IEEE80211_QOS_TID : 0;
prsc = &k->k_rsc[tid];
- } else if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=
- IEEE80211_FC0_TYPE_MGT) {
- prsc = &k->k_rsc[0];
} else /* 11w: management frames have their own counters */
prsc = &k->k_mgmt_rsc;
diff --git a/sys/net80211/ieee80211_crypto_tkip.c b/sys/net80211/ieee80211_crypto_tkip.c
index 5bde7c517b3..032ffdbdff3 100644
--- a/sys/net80211/ieee80211_crypto_tkip.c
+++ b/sys/net80211/ieee80211_crypto_tkip.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_crypto_tkip.c,v 1.8 2008/08/27 09:05:04 damien Exp $ */
+/* $OpenBSD: ieee80211_crypto_tkip.c,v 1.9 2008/09/27 15:00:08 damien Exp $ */
/*-
* Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>
@@ -150,20 +150,9 @@ ieee80211_tkip_mic(struct mbuf *m0, int off, const u_int8_t *key,
((const struct ieee80211_frame_addr4 *)wh)->i_addr4);
break;
}
- if ((wh->i_fc[0] &
- (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) ==
- (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS)) {
- if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) ==
- IEEE80211_FC1_DIR_DSTODS) {
- const struct ieee80211_qosframe_addr4 *qwh4 =
- (const struct ieee80211_qosframe_addr4 *)wh;
- wht.i_pri = qwh4->i_qos[0] & 0xf;
- } else {
- const struct ieee80211_qosframe *qwh =
- (const struct ieee80211_qosframe *)wh;
- wht.i_pri = qwh->i_qos[0] & 0xf;
- }
- } else
+ if (ieee80211_has_qos(wh))
+ wht.i_pri = ieee80211_get_qos(wh) & IEEE80211_QOS_TID;
+ else
wht.i_pri = 0;
wht.i_pad[0] = wht.i_pad[1] = wht.i_pad[2] = 0;
@@ -334,6 +323,7 @@ ieee80211_tkip_decrypt(struct ieee80211com *ic, struct mbuf *m0,
u_int64_t tsc, *prsc;
u_int32_t crc, crc0;
u_int8_t *ivp, *mic0;
+ u_int8_t tid;
struct mbuf *n0, *m, *n;
int hdrlen, left, moff, noff, len;
@@ -352,24 +342,10 @@ ieee80211_tkip_decrypt(struct ieee80211com *ic, struct mbuf *m0,
return NULL;
}
- /* retrieve last seen packet number for this frame TID */
- if ((wh->i_fc[0] &
- (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) ==
- (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS)) {
- u_int8_t tid;
- if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) ==
- IEEE80211_FC1_DIR_DSTODS) {
- struct ieee80211_qosframe_addr4 *qwh4 =
- (struct ieee80211_qosframe_addr4 *)wh;
- tid = qwh4->i_qos[0] & 0x0f;
- } else {
- struct ieee80211_qosframe *qwh =
- (struct ieee80211_qosframe *)wh;
- tid = qwh->i_qos[0] & 0x0f;
- }
- prsc = &k->k_rsc[tid];
- } else
- prsc = &k->k_rsc[0];
+ /* retrieve last seen packet number for this frame priority */
+ tid = ieee80211_has_qos(wh) ?
+ ieee80211_get_qos(wh) & IEEE80211_QOS_TID : 0;
+ prsc = &k->k_rsc[tid];
/* extract the 48-bit TSC from the TKIP header */
tsc = (u_int64_t)ivp[2] |
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index a98174527c0..38428f009a0 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_input.c,v 1.104 2008/09/01 19:41:10 damien Exp $ */
+/* $OpenBSD: ieee80211_input.c,v 1.105 2008/09/27 15:00:08 damien Exp $ */
/*-
* Copyright (c) 2001 Atsushi Onoe
@@ -102,24 +102,19 @@ void ieee80211_recv_action(struct ieee80211com *, struct mbuf *,
* Retrieve the length in bytes of a 802.11 header.
*/
u_int
-ieee80211_get_hdrlen(const void *data)
+ieee80211_get_hdrlen(const struct ieee80211_frame *wh)
{
- const u_int8_t *fc = data;
- u_int size = sizeof(struct ieee80211_frame);
-
- /* NB: doesn't work with control frames */
- KASSERT((fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL);
-
- if ((fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
- size += IEEE80211_ADDR_LEN; /* i_addr4 */
- if ((fc[0] & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) ==
- (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS)) {
- size += sizeof(u_int16_t); /* i_qos */
- if (fc[1] & IEEE80211_FC1_ORDER)
- size += sizeof(u_int32_t); /* i_ht */
- } else if ((fc[0] & IEEE80211_FC0_TYPE_MASK) ==
- IEEE80211_FC0_TYPE_MGT && (fc[1] & IEEE80211_FC1_ORDER))
- size += sizeof(u_int32_t); /* i_ht */
+ u_int size = sizeof(*wh);
+
+ /* NB: does not work with control frames */
+ KASSERT(ieee80211_has_seq(wh));
+
+ if (ieee80211_has_addr4(wh))
+ size += IEEE80211_ADDR_LEN; /* i_addr4 */
+ if (ieee80211_has_qos(wh))
+ size += sizeof(u_int16_t); /* i_qos */
+ if (ieee80211_has_htc(wh))
+ size += sizeof(u_int32_t); /* i_ht */
return size;
}
@@ -181,22 +176,12 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
}
}
/* check and save sequence control field, if present */
- if (ic->ic_state != IEEE80211_S_SCAN &&
- type != IEEE80211_FC0_TYPE_CTL) {
+ if (ieee80211_has_seq(wh) &&
+ ic->ic_state != IEEE80211_S_SCAN) {
nrxseq = letoh16(*(u_int16_t *)wh->i_seq) >>
IEEE80211_SEQ_SEQ_SHIFT;
- if ((wh->i_fc[0] &
- (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) ==
- (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS)) {
- if (dir == IEEE80211_FC1_DIR_DSTODS) {
- struct ieee80211_qosframe_addr4 *qwh4 =
- (struct ieee80211_qosframe_addr4 *)wh;
- tid = qwh4->i_qos[0] & 0x0f;
- } else {
- struct ieee80211_qosframe *qwh =
- (struct ieee80211_qosframe *)wh;
- tid = qwh->i_qos[0] & 0x0f;
- }
+ if (ieee80211_has_qos(wh)) {
+ tid = ieee80211_get_qos(wh) & IEEE80211_QOS_TID;
orxseq = &ni->ni_qos_rxseqs[tid];
} else
orxseq = &ni->ni_rxseq;
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index 7accd434342..b508e606597 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_output.c,v 1.77 2008/09/03 19:53:37 damien Exp $ */
+/* $OpenBSD: ieee80211_output.c,v 1.78 2008/09/27 15:00:08 damien Exp $ */
/* $NetBSD: ieee80211_output.c,v 1.13 2004/05/31 11:02:55 dyoung Exp $ */
/*-
@@ -69,7 +69,6 @@
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_priv.h>
-enum ieee80211_edca_ac ieee80211_up_to_ac(struct ieee80211com *, int);
int ieee80211_classify(struct ieee80211com *, struct mbuf *);
int ieee80211_mgmt_output(struct ifnet *, struct ieee80211_node *,
struct mbuf *, int);
diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h
index 15b316c4efa..55c24d6e2e1 100644
--- a/sys/net80211/ieee80211_proto.h
+++ b/sys/net80211/ieee80211_proto.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_proto.h,v 1.34 2008/09/01 19:41:10 damien Exp $ */
+/* $OpenBSD: ieee80211_proto.h,v 1.35 2008/09/27 15:00:08 damien Exp $ */
/* $NetBSD: ieee80211_proto.h,v 1.3 2003/10/13 04:23:56 dyoung Exp $ */
/*-
@@ -59,7 +59,7 @@ extern void ieee80211_proto_detach(struct ifnet *);
struct ieee80211_node;
struct ieee80211_rxinfo;
struct ieee80211_rsnparams;
-extern u_int ieee80211_get_hdrlen(const void *);
+extern u_int ieee80211_get_hdrlen(const struct ieee80211_frame *);
extern void ieee80211_input(struct ifnet *, struct mbuf *,
struct ieee80211_node *, struct ieee80211_rxinfo *);
extern int ieee80211_output(struct ifnet *, struct mbuf *, struct sockaddr *,
@@ -100,6 +100,7 @@ extern int ieee80211_pwrsave(struct ieee80211com *, struct mbuf *,
extern struct mbuf *ieee80211_decap(struct ifnet *, struct mbuf *, int);
#define ieee80211_new_state(_ic, _nstate, _arg) \
(((_ic)->ic_newstate)((_ic), (_nstate), (_arg)))
+extern enum ieee80211_edca_ac ieee80211_up_to_ac(struct ieee80211com *, int);
extern u_int8_t *ieee80211_add_capinfo(u_int8_t *, struct ieee80211com *,
const struct ieee80211_node *);
extern u_int8_t *ieee80211_add_ssid(u_int8_t *, const u_int8_t *, u_int);